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的函数了。

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