您好,登錄后才能下訂單哦!
本篇文章為大家展示了Copy函數(shù)如何在Python項(xiàng)目中使用,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
1、對象引用的傳值或者傳引用
Python中的對象賦值實(shí)際上是簡單的對象引用。也就是說,當(dāng)你創(chuàng)建一個(gè)對象,然后把它賦值給另一個(gè)變量的時(shí)候,Python并沒有拷貝這個(gè)對象,而是拷貝了這個(gè)對象的引用。這種方式相當(dāng)于值傳遞和引用傳遞的一種綜合。如果函數(shù)收到的是一個(gè)可變對象(比如字典或者列表)的引用,就能修改對象的原始值--相當(dāng)于通過“引用傳遞”來賦值。如果函數(shù)收到的是一個(gè)不可變變量(比如數(shù)字、字符串或者元祖)的引用,就不能直接修改原始對象--相當(dāng)于通過“值傳遞”來賦值。
先看一個(gè)數(shù)字傳遞的例子:
>>> def test(a): ... print id(a) ... a = a + 1 ... print id(a) ... return a ... >>> b =19 >>> id(b) 38896272 >>> c = test(b) 38896272 38896260 >>> id(b) 38896272 >>> b 19
id函數(shù)可以獲得對象的內(nèi)存地址.
很明顯從上面例子可以看出,將b變量作為參數(shù)傳遞給了test函數(shù),傳遞了b的一個(gè)引用,把b的地址傳遞過去了,所以在函數(shù)內(nèi)獲取的變量a的地址跟變量b的地址是一樣的,但是在函數(shù)內(nèi),對a進(jìn)行賦值運(yùn)算,a的值從19變成了20,實(shí)際上19和20所占的內(nèi)存空間都還是存在的,賦值運(yùn)算后,a指向20所在的內(nèi)存。而b仍然指向19所在的內(nèi)存,所以后面打印b,其值還是19.
另外,關(guān)于整數(shù)變量的id,所有在[-5,256]范圍內(nèi)的整數(shù),python是提前分配好空間放在數(shù)組里初始化好的,所以兩個(gè)變量如果是相同的小整數(shù),對象都是最開始初始化的那一個(gè),所以兩個(gè)變量的id是一樣的。
所有在[-5,256]范圍外的整數(shù)的話,每次都會(huì)新建一個(gè)的,所以id會(huì)改變
>>> a = 256 >>> id(a) 43340980 >>> b = 256 >>> id(b) 43340980 # a和b的id相同 >>> a = 257 >>> id(a) 44621040 >>> b = 257 >>> id(b) 44620908 # a和b的id不同 >>> a = -5 >>> id(a) 43338160 >>> b = -5 >>> id(b) 43338160 >>> a = -6 >>> id(a) 44621184 >>> b = -6 >>> id(b) 44621112
再看一個(gè)列表傳遞的例子:
>>> def test(a): ... print id(a) ... a[0] = 100 ... print id(a) ... return a ... >>> b = [7,8,9,10] >>> id(b) 46408088 >>> c = test(b) 46408088 46408088 >>> id(b) 46408088 >>> b [100, 8, 9, 10]
從上面例子可以看出,將b變量作為參數(shù)傳遞給了test函數(shù),傳遞了b的一個(gè)引用,把b的地址傳遞過去了,所以在函數(shù)內(nèi)獲取的變量a的地址跟變量b的地址是一樣的,但是在函數(shù)內(nèi),對a進(jìn)行賦值運(yùn)算,a[0]的值從7變成了100,但是a的id并沒有發(fā)生變化,還是和變量b的地址是一樣的,所以后面打印b,b[0]的值也從7變成了100.
2、關(guān)于可變變量和不可變變量:
這里的可變不可變,是指內(nèi)存中的那塊內(nèi)容(value)是否可以被改變
不可變變量:
number: int, float, str, 元組。--指它的部分(比如element,attribute不能改變)不能改變;并不是整體不可變。另外,Python所有變量皆對象。int也是一個(gè)對象。
>>> a = 10000 >>> id(a) 46573412 >>> a = 10000000 >>> id(a) 46573460 #數(shù)字變量重新賦值后,id發(fā)生了變化 >>> s = 'abc' >>> s[1] = d #字符串變量中的某一個(gè)元素不能進(jìn)行改變 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'str' object does not support item assignment >>> id(s) 39103328 >>> s = 'ttt' >>> id(s) #字符串變量進(jìn)行重新賦值后,id發(fā)生了變化 46425368
從上面的例子中可以看出,數(shù)字變量、字符變量在重新賦值后,id都會(huì)發(fā)生變化,這是因?yàn)椴豢勺冏兞康馁x值是通過在內(nèi)存中新申請一塊區(qū)域,把新的值存儲(chǔ)到該區(qū)域,然后改變不可變變量的引用,指向新的內(nèi)存區(qū)域,從而改變了不可變變量的值。
可變變量
class, class instance;列表,dict,
例1.可變變量中元素的賦值
>>> list = [1,2,3] >>> id(list) 45486568 >>> for i in list: ... print id(i) 40207208 40207196 40207184 >>> list[0] = 0 >>> id(list) 45486568 # 變量的id并沒有發(fā)生改變 >>> for i in list: ... print id(i) 40207220 # 該元素的id發(fā)生了改變 40207196 40207184 例2.可變變量的賦值 >>> list = [1,2,3] >>> id(list) 43783392 >>> list =[2,3,5] >>> id(list) # 該變量的id發(fā)生了改變 44454296
從上面的例子可以看出,列表中的元素重新賦值,整個(gè)列表的id不會(huì)發(fā)生改變,但是該元素的id會(huì)發(fā)生該生。因?yàn)榱斜碇写鎯?chǔ)的其實(shí)是對各個(gè)元素的引用,所以對該元素賦值的結(jié)果就是元素的引用發(fā)生了改變。
總之,無論是可變變量還是不可變變量,只要對整個(gè)變量進(jìn)行賦值,Python都在內(nèi)存中新申請一塊區(qū)域,把新的值存儲(chǔ)到該區(qū)域,然后改變不可變變量的引用,指向新的內(nèi)存區(qū)域;如果可變變量中的元素進(jìn)行賦值,支隊(duì)導(dǎo)致該元素的變化,不會(huì)導(dǎo)致父對象的變化。
3、 深拷貝 Vs 淺拷貝
copy.copy() 淺拷貝
copy.deepcopy() 深拷貝
淺拷貝是新創(chuàng)建了一個(gè)跟原對象一樣的類型,但是其內(nèi)容是對原對象元素的引用。這個(gè)拷貝的對象本身是新的,但內(nèi)容不是。如果原對象的元素包含不是基本數(shù)據(jù)結(jié)構(gòu),而是list、dict或者對象的話,那么原對象或者拷貝對象改變list、dict或者對象里面的內(nèi)容的話,會(huì)導(dǎo)致二者同時(shí)發(fā)生改變。
深拷貝則是對原對象的完全拷貝,包含對象里面的子對象的拷貝,因此拷貝對象和原對象二者是完全獨(dú)立,任何一方的改變對另外一方都不會(huì)產(chǎn)生任何的影響。
>>> import copy >>> list = [1, 2, [3, 4]] >>> copy_list = copy.copy(list) >>> deepcopy_list = copy.deepcopy(list) >>> >>> id(list) 44454296 >>> id(copy_list) 44515736 >>> id(deepcopy_list) 44455736 >>> >>> for k in list: ... print id(k) 43338088 43338076 44430120 >>> for k in copy_list: ... print id(k) 43338088 43338076 44430120 # copy對象的內(nèi)容和原對象完全一樣 >>> for k in deepcopy_list: ... print id(k) 43338088 43338076 44457456 # deepcopy對象的內(nèi)容和原對象有區(qū)別:列表元素的id不一樣;數(shù)字元素id一樣,原因是所有相同數(shù)字的變量的引用都是一樣的。 >>> >>> list[2][0] = 30 >>> list [1, 2, [30, 4]] >>> copy_list [1, 2, [30, 4]] # 原對象的子對象中的元素發(fā)生改變后,會(huì)導(dǎo)致copy對象發(fā)生同樣的改變 >>> deepcopy_list [1, 2, [3, 4]] #原對象的子對象中的元素發(fā)生改變后,不會(huì)導(dǎo)致deepcopy對象發(fā)生同樣的改變
上述內(nèi)容就是Copy函數(shù)如何在Python項(xiàng)目中使用,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。