Python 的赋值语句不复制对象,而是创建目标和对象的绑定关系。
>>> a = 1
>>> id(a)
140731276990112
>>> b = a
>>> id(b)
140731276990112
上面的第行代码将值1
的地址绑定给变量a
id(a)
返回变量a中的值的内存地址
接下来语句b = a
将变量a
赋值给变量b
,不会创建新的值,只会把变量a
指向的内存地址绑定给变量b
,这样a
,b
指向相同的内存地址,所以它们的id()
相等。
对于自身可变,或包含可变项的集合,有时要生成副本用于改变操作,而不必改变原始对象。通过copy
模块可以实现浅拷贝
和深拷贝
。
深浅拷贝的区别仅与复合对象(即包含列表或类的实例等其他相关对象)相关:
- 浅拷贝 构造一个新的复合对象,然后(尽可能的范围内)将原对象中找到的对象的引用插入其中。
- 深拷贝 构造一个新的复合对象,然后,递归的将再原始对象找到的对象的副本插入其中。
浅拷贝
>>> import copy
>>> ls = [1, 2, ['a', 'b']]
>>> ln = copy.copy(ls)
>>> print(id(ls), id(ln))
2930321101952 2930321101056
>>> print(id(ls[2]), id(ln[2]))
2930321100736 2930321100736
对ls
进行浅拷贝,会生成一个新的列表对象,所以ls
,ln
的id()
不相同。然后将ls
里元素的引用插入ln
中,所以ls[2]
和ln[2]
的id()
相同。
这是修改ls
的第三个元素,ln
也会改变。
>>> ls[2][0] = 'A'
>>> print(ls)
[1, 2, ['A', 'b']]
>>> print(ln)
[1, 2, ['A', 'b']]
深拷贝
>>> import copy
>>> ls = [1, 2, ['a', 'b']]
>>> ln = copy.deepcopy(ls)
>>> print(id(ls), id(ln))
2930321640128 2930321101952
>>> print(id(ls[2]), id(ln[2]))
2930321100480 2930321100352
对ls
进行深拷贝,会生成一个新的列表对象,所以ls
,ln
的id()
不相同。然后将递归的将ls
里元素的副本插入ln
中,所以ls[2]
和ln[2]
的id()
不相同。