在 Python 之中,如果想要复制一个对象就免不了要理解浅复制与深复制。这也是 Python 与其他语言的区别之一。
Python 的数据存储方式与其他语言不同。当你定义了一个变量:
a = [0, 1, 2, 3, 4]
这在 Python 中就表示在内存中开辟了一个空间,这个空间里存储了[0, 1, 2, 3, 4],然后变量a里存储这个内存空间的地址。
>>> a=[0, 1, 2, 3, 4] >>> b = a >>> print(b) [0, 1, 2, 3, 4] >>> a = [1] >>> print(a) [1] >>> print(b) [0, 1, 2, 3, 4]
这里我们可以清楚的看到,b = a 相当于在 b 中存储了当前 a 中记录的内存地址。当 a = [1] 时 Python 解释器又在内存中开辟了一个空间存储 [1] 并且在 a 中存储了它的地址。
但是整个过程中 b 依然存储了当初的 [0, 1, 2, 3, 4] 的存储地址,所以 b 的内容不变。
>>> a = [0, 1, 2, 3, 4] >>> b = a >>> a[0] = 99999 >>> print(a) [99999, 1, 2, 3, 4] >>> print(b) [99999, 1, 2, 3, 4]
这里我修改了 a[0] 的值,相当于修改了在内存中存储的值,a 与 b 存储着一样的地址,当里面的内容改变时,自然输出的值也都改变了。
Python 中的浅复制与深复制:
理解了 Python 中的变量存储方式,我们再来说什么是浅复制与深复制。
>>> import copy >>> a = [0, 1, 2, 3, 4] >>> b = copy.copy(a) >>> c = copy.deepcopy(a) >>> a[0] = 10086 >>> print(b) [0, 1, 2, 3, 4] >>> print(c) [0, 1, 2, 3, 4] >>> print(a) [10086, 1, 2, 3, 4]
可以看到,当 a 时一个简单的字典、元祖、列表时,使用浅复制或深复制时修改 a 的值都不会使复制的对象值发生变化。
>>> import copy >>> a = [0, 1, 2, [0, 1]] >>> b = copy.copy(a) >>> c = copy.deepcopy(a) >>> a[3][0] = 10086 >>> print(a) [0, 1, 2, [10086, 1]] >>> print(b) [0, 1, 2, [10086, 1]] >>> print(c) [0, 1, 2, [0, 1]]
但是当 a 是一个复杂的列表时,例如这里时一个嵌套了列表的列表。当修改 a 中嵌套列表的值就会使浅复制的 b 中的值也发生改变。
结论
直接赋值 :只是将内存地址给了对象。
浅复制:只将父对象拷贝了一遍。
深复制:将父对象与子对象都拷贝了。