日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python深浅拷贝教程-面试必问内容

發布時間:2025/3/20 python 10 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python深浅拷贝教程-面试必问内容 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 賦值

在Python中,賦值其實就是對象的引用。

a = 9999 b = a print(a) #ouput:9999 print(b) #ouput:9999 print(id(a)) #ouput:1869259054928 print(id(b)) #ouput:1869259054928


這樣賦值后,b和a不僅在值上相等,而且是同一個對象,也就是說在堆內存中只有一個數據對象9999,這兩個變量都指向這一個數據對象。從數據對象的角度上看,這個數據對象有兩個引用,只有這兩個引用都沒了的時候,堆內存中的數據對象9999才會等待垃圾回收器回收。

需要注意的是,它和下面的賦值過程是不等價的:

a = 9999 b = 9999 print(id(a)) #ouput:1869266158672 print(id(b)) #ouput:1869266158768


雖然a和b的值相等,但他們不是同一個對象,這時候在堆內存中有兩個數據對象,只不過這兩個數據對象的值相等。

不可變對象

對于不可變對象,修改變量的值意味著在內存中要新創建一個數據對象

''' 學習中遇到問題沒人解答?小編創建了一個Python學習交流QQ群:725638078 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' >>> a = 9999 >>> b = a >>> id(a) 2625562451792 >>> id(b) 2625562451792 >>> a = 20000 >>> id(a) 2625564836944 >>> id(b) 2625562451792


在a重新賦值之前,b和a都指向堆內存中的同一個數據對象9999,但a重新賦值后,因為數值類型9999是不可變對象,不能在原始內存塊中直接修改數據,所以會新創建一個數據對象保存20000,最后a將指向這個20000對象。這時候b仍然指向9999,而a則指向20000。

可變對象

對于可變對象,比如列表,它是在"原處修改"數據對象的。比如修改列表中的某個元素,列表的地址不會變,還是原來的那個內存對象,所以稱之為"原處修改"。

例如:

>>> L1 = [1,2,3] >>> L2 = L1 >>> L1[0] = 999 >>> L1,L2 ([999, 2, 3], [999, 2, 3]) >>> id(L1) 2625562620872 >>> id(L2) 2625562620872


在L1[0]賦值的前后,數據對象[1,2,3]的地址一直都沒有改變,但是這個列表的第二個元素的值已經改變了。因為L1和L2都指向這個列表,所以L1修改第一個元素后,L2的值也相應地到影響。也就是說,L1和L2仍然是同一個列表對象。

面試中會可能遇到的問題:

1.為啥一直在用9999這個數?

答:

  • 9是我的幸運數字😂

  • 因為9999不是小整數(移步文章末尾)

2.為什么在Pycharm內的輸出結果和上面內容不一致?

答:首先 Python給[-5,256]以內值分配了空間, 超出的就需要重新分配。 而Pycharm不遵循這個,因為 Pycharm是放到腳本里面編譯的,而不是在解釋器里面,腳本編譯是一次性編譯的會產生編譯文件,所以內存地址會復用,所以輸出的id效果不一致。

2 . 淺拷貝

淺拷貝: 只拷貝第一層的數據。

在python中賦值操作或copy模塊的copy()就是淺拷貝

怎么理解拷貝第一層的數據,先來看一個嵌套的數據結構:

L1 = [1,2,3] L2 = [1,2,[3,33,333]]

L1只有一層深度,L2有兩層深度, 淺拷貝時只拷貝第一層的數據作為副本,深拷貝遞歸拷貝所有層次的數據作為副本。

例如:

''' 學習中遇到問題沒人解答?小編創建了一個Python學習交流QQ群:725638078 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' >>> import copy >>> L = [9,99,999] >>> a = [1,2,L] >>> b = copy.copy(a) >>> a,b ([1, 2, [9, 99, 999]], [1, 2, [9, 99, 999]]) >>> id(a),id(b) # 不相等 (2625565288456, 2625565288776) >>> id(a[2]) 2625565288328 >>> id(b[2]) # 相等 2625565288328 >>> L[0] = 0 >>> a,b ([1, 2, [0, 99, 999]], [1, 2, [0, 99, 999]])


a 和 b 是一個獨立的對象,但他們的子對象還是指向統一對象(是引用)。

3 深拷貝

深拷貝:遞歸拷貝所有層次的數據

Python中copy模塊的deepcopy()是深拷貝 ,比如:

>>> L = [9,99,999] >>> a = [1,2,L] >>> b = copy.deepcopy(a) >>> a,b ([1, 2, [9, 99, 999]], [1, 2, [9, 99, 999]]) >>> id(a),id(b) # 不相等 (2625565169224, 2625565169288) >>> id(a[2]) 2625565169480 >>> id(b[2]) # 不相等 2625565169416 >>> L[0] = 0 >>> a,b ([1, 2, [0, 99, 999]], [1, 2, [9, 99, 999]])


深度拷貝, a 和 b 完全拷貝了父對象及其子對象,兩者是完全獨立的。

一般來說,淺拷貝或者引用賦值就是我們所經常用的操作,只有少數情況下( 數據序列化、要傳輸、要持久化 ),才需要深拷貝操作,但是這些操作一般都內置在對應函數中,無需手動去深拷貝。

總結:

  • 淺拷貝:內存地址
  • 深拷貝:數據內容

4 早已存在的小整數

數值對象是不可變對象,理論上每個數值都會創建新對象。

但實際上并不是這樣,對于 [-5,256]這個區間內的小整數,因為Python內部引用過多,這些整數在python運行的時候就事先創建好并編譯好對象了。所以,a=2, b=2, c=2根本不會在內存中新創建數據對象2,而是引用早已創建好的初始化數值2。

>>> a=2 >>> b=2 >>> a is b True

對于超出小整數范圍的數值,每一次使用數值對象都創建一個新數據對象。

例如:

>>> a=9999 >>> b=9999 >>> a is b False

但是也有特殊的情況:

''' 學習中遇到問題沒人解答?小編創建了一個Python學習交流QQ群:725638078 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' >>> a=9999;b=9999 >>> a is b True >>> a,b=9999,9999 >>> a is b True

為什么會這樣呢?

原因是 Python解析代碼的方式是按行解釋的,讀一行解釋一行,創建了第一個9999時發現本行后面還要使用一個9999,于是b也會使用這個9999,所以它返回True。而前面的換行賦值的方式,在解釋完一行后就會立即忘記之前已經創建過9999的數據對象,于是會為b創建另一個9999,所以它返回False。

如果在Python的文件中執行,則在同一作用域內,a is b是一直會是True的,這和代碼塊作用域有關: 整個py文件是一個模塊作用域 ,可以看我之前的內容

a = 9999 b = 9999 print(a is b) # Truedef func():c = 9999d = 9999print(c is d) # Trueprint(a is c) # Falsefunc()

這也是為什么相同的代碼在pycharm和cmd輸出的結果會不一致的原因。

結尾給大家推薦一個非常好的學習教程,希望對你學習Python有幫助!

Python基礎入門教程推薦:更多Python視頻教程-關注B站:Python學習者

【Python教程】全網最容易聽懂的1000集python系統學習教程(答疑在最后四期,滿滿干貨)

總結

以上是生活随笔為你收集整理的Python深浅拷贝教程-面试必问内容的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。