【Python学习笔记】深拷贝和浅拷贝
最近,在使用列表的append
时发现更新后,列表的数值都是相同的。究其原因发现,因为数值对应的变量在更新时,指向的内存地址是相同的。
例如:
a = []
b = {'num':0}
for i in range(3):
b['num'] += 1
a.append(b)
a
在字典或者列表使用变量相互赋值,会出现上述情况,这或许和数据类型有关:可哈希对象与不可哈希对象。本想出现[{'num': 1}, {'num': 2}, {'num': 3}]
的结果,就是因为变量在更新时指向的内存地址是相同的。
- 可哈希的对象,即不可变的数据结构:数字类型(int,float,bool)、字符串str、元组tuple、自定义类的对象。它的生存期内必须不可变,对于不可变类型而言,不同的值意味着不同的内存
- 不可哈希对象,可变的数据结构:字典dict、列表list、集合set。对于可变对象而言,比如一个列表,更改列表的值,但是对象的地址本身是不变的。
a = []
b = 0
for i in range(3):
b += 1
a.append(b)
a
这时,可以采用深拷贝和浅拷贝解决。
深拷贝
,是指重新分配一块内存,创建一个新的对象,并且将原对象中的元素,以递归的方式,通过创建新的子对象拷贝到新对象中。
浅拷贝
,指的是重新分配一块内存,创建一个新的对象,但里面的元素是原对象中各个子对象的引用。
# 深拷贝
import copy
copy.deepcopy(b)
# 浅拷贝
b.copy
copy.copy(b)
对数据采用浅拷贝的方式时,如果原对象中的元素不可变,与深拷贝相同;但如果元素可变,浅拷贝通常会不一样。
a = [[1, 2], (3, 4)]
b = a.copy()
print("a1:",a)
print("b1:",b)
print("*"*30)
#对象为整型,不可变
a.append(5)
print("a2:",a)
print("b2:",b)
print("*"*30)
#对象为列表,可变
a[0].append(3)
print("a3:",a)
print("b3:",b)