Python深拷贝、浅拷贝

Python中有三种拷贝:

  • =:完全不拷贝,指针指向同一块内存数据
  • copy.copy():浅拷贝,为新变量开创内存空间,但是如果变量里面有子变量,则子变量只是指向原先对应的内存空间。
  • copy.deepcopy():深拷贝,为新变量重新开创内存空间,变量里面如果有子变量也全都重新开内存来存储。

拷贝让人混淆的,一般有这几种情况:

  • 变量有子变量的情况,如v = [ [1,2], [3,4] ], 甚至v = [ [[1,2], [3,4]], [[5,6], [7,8]] ]
  • 向列表或字典插入元素的情况,如v.append(123)且时候,v的复制品是否也会变化?
  • 向列表或字典的子变量插入元素时候,复制品是否也会变化?

当变量有子变量的情况下:

import copy

original = [ [1,2], [3,4] ]

reference  = original
shallow = copy.copy(original) 
deep = copy.deepcopy(original) 

# -----RESULTS ------
# Reference >>> id(reference) == id(original)
# Shallow copy >>> id(shallow) != id(original)
# Deep copy >>> id(deep) != id(original)
#         but >>> id(deep[0]) == id(original[0])

向列表插入元素的情况下:

import copy

original = [ [1,2], [3,4] ]
reference  = original
shallow = copy.copy(original) 
deep = copy.deepcopy(original) 

original.append( [5,6] )

# -----RESULTS ------
# Original >>> original == [ [1,2], [3,4], [5,6] ]
# Reference >>> reference == [ [1,2], [3,4], [5,6] ]
# Shallow copy >>> shallow == [ [1,2], [3,4] ]
# Deep copy >>> deep == [ [1,2], [3,4] ]

为什么浅拷贝没有变化呢?
因为浅拷贝,只是拷贝了原变量的子变量的引用,也就是说,原变量增加的一个子变量,不会使浅拷贝增加一个引用。
在浅拷贝后,实际上新变量shallow中存储的内容如下:

shallow == [ address_of_[1,2], address_of_[3,4] ]

也就是说这里的逻辑关系是:只有当之前的子变量[1,2][3,4]发生变动时,变量shallow才会变化。
但是原变量original本身的扩充变化,完全和它无关了。

使用列表和字典自带的.copy()方法:
list和dict所自带的.copy()方法,实际上是浅拷贝。即如果new = original.copy(),那么这个new变量是浅拷贝出来的。

你可能感兴趣的:(Python深拷贝、浅拷贝)