assignment,shallow copy,deep copy,引用,不可變對象

要了解assignment,shallow copy,deep copy這3個概念,就必須明白Python的所有變量都只是引用。
引用
比如
i =1; ii=i; iii=ii; 
>>> for x in i, ii, iii:
...     id(x)   # id是Python中類似於獲取對象內存地址的函數

... 
1431032272
1431032272
1431032272
此時內存是這樣的    
Python的assignment不會產生新對象,而僅僅生成一個對象的引用。

再看下例(不可變對象):
i = 10000; id(i); i = 100001; id(i)
51348944
51356032
>>> i=1; ii=i; ii=2;id(i);id(ii);
1431032272
1431032288

爲什麼?因爲在Python基礎類型中,數字,字符串,元組等都是不可變對象,即生成後不能改變值的對象,而你現在要改變它,只能是新生成一個對象了。


再談copy與deep_copy就簡單了,參考Python官方文檔:

The difference between shallow and deep copying is only relevant for compound objects (objects that contain other objects, like lists or class instances):

  • shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original.
  • deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original. 
也就是說shallow copy只管第一層的,再往下我就不管了。
>>> lst=[1,2,3,4]; lst1=copy.copy(lst);id(lst);id(lst1);
51408408
51535384
>>> id(lst[0]);id(lst1[0]);
1431032272
1431032272

而對於deepcopy而言,不用想太多,那已經完全不是原來的你;試一試。
>>> lst=[1,2,3,4]; lst1=copy.deepcopy(lst);id(lst);id(lst1);
13043152
51408408
>>> id(lst[0]);id(lst1[0]);
1431032272
1431032272
!!!OMG,爲什麼deepcopy還是一樣,別急,那是因爲對於不可變對象,Python明顯採用的是lazy算法,直到有改變值的操作時候才生成新的對象;如果你不是用的不可變對象,結果自然就符合我們心中的情況了。
>>> lst=[[1],2,3,4]; lst1=copy.deepcopy(lst);id(lst);id(lst1);
13050344
13043152
>>> id(lst[0]);id(lst1[0]);
13050264
13045672

需要注意的是deepcopy的recursively,不是每一個object都可以deepcopy的,而且消耗也太大。

綜合來看,某些情況可能需要我們定義copy_xxx的函數了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章