赞
踩
这段时间在写一个软件,但是近期在测试时发现了有问题,经过多次测试和排查,终于找到了问题所在,就是Python的对象引用及拷贝问题。下面讲解梳理下这方面的知识点:
直接赋值:引用当前对象,不涉及新内存的创建
浅拷贝:仅拷贝当前对象,不拷贝当前对象的子对象
深拷贝:当前对象及其子对象均拷贝
下面用例子来讲解这几种方法的区别
一、直接赋值
a = [1,2,3]
b = a
print("更改前:",a,b)
b.append(4)
print("更改后:",a,b)
输出结果如下:
更改前: [1, 2, 3] [1, 2, 3]
更改后: [1, 2, 3, 4] [1, 2, 3, 4]
这里我们可以看出,当b更改时,a也随着更改,因为b只是a的一个引用,相当于a的别名。
图1:直接赋值图示
二、浅拷贝
a = [1,2,3]
b = a.copy() # 或者b = a[:]也可以
print("更改前:",a,b)
b.append(4)
print("更改后:",a,b)
# 为探究子对象的拷贝情况,这里用字典来说明
c = {'a':[1,2,3]}
d1 = c.copy()
d2 = c.copy()
print("更改前:",c,d1,d2)
d1['a'] = 2
d2['a'][0] = 0
print("更改后:",c,d1,d2)
输出结果如下:
更改前: [1, 2, 3] [1, 2, 3]
更改后: [1, 2, 3] [1, 2, 3, 4]
更改前: {'a': [1, 2, 3]} {'a': [1, 2, 3]} {'a': [1, 2, 3]}
更改后: {'a': [0, 2, 3]} {'a': 2} {'a': [0, 2, 3]}
这里可以看出,浅拷贝的话对当前对象来说,相当于备份了一份,更改哪一份对另一份都没有影响(例如a与b,c与d1),若当前对象还有子对象的话,浅拷贝时,子对象相当于引用,并没有拷贝(例如c与d2),所以当前对象的子对象更改时,浅拷贝对象的子对象也会更改。
图2:浅拷贝图示
三、深拷贝
import copy # 深拷贝需要引入copy包
c = {'a':[1,2,3]}
d1 = copy.deepcopy(c)
d2 = copy.deepcopy(c)
print("更改前:",c,d1,d2)
d1['a'] = 2
d2['a'][0] = 0
print("更改后:",c,d1,d2)
输出结果如下:
更改前: {'a': [1, 2, 3]} {'a': [1, 2, 3]} {'a': [1, 2, 3]}
更改后: {'a': [1, 2, 3]} {'a': 2} {'a': [0, 2, 3]}
这里可以看出,深拷贝时,当前对象及其子对象均拷贝了,一份拷贝修改后,不会对原始数据造成影响。
图3:深拷贝图示
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。