深拷贝和浅拷贝都是对象的拷贝,都会生成一个看起来相同的对象,他们本质的区别是拷贝出来的对象的地址是否和原对象一样,也就是地址的复制还是值的复制的区别。
深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝
不可变元素包括
int,float,complex,long,str,unicode,tuple
类型 | 赋值 | 浅拷贝 | 深拷贝 |
---|---|---|---|
不可变元素 | 变 | 不 | 不 |
可变元素 | 变 | 变 | 不 |
赋值
原始列表改变,赋值的列表也会做相同的改变
a=[1,2,3,4,5,['a','b']]
#原始对象
b=a#赋值,传对象的引用
print('a:',a,id(a),id(a[5]))#输出a的值,地址,子列表的地址
print('b:',b,id(b),id(b[5]))#输出b的值,地址,子列表的地址
a.append(6)
a[5].append('c')
print('a:',a,id(a),id(a[5]))#输出a的值,地址,子列表的地址
print('b:',b,id(b),id(b[5]))#输出b的值,地址,子列表的地址
"""
a: [1, 2, 3, 4, 5, ['a', 'b']] 1932860753344 1932861322432
b: [1, 2, 3, 4, 5, ['a', 'b']] 1932860753344 1932861322432
a: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6] 1932860753344 1932861322432
b: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6] 1932860753344 1932861322432
"""
浅拷贝
没有拷贝子列表,所以原始子列表数据改变,复制的子列表对象会改变
import copy
a=[1,2,3,4,5,['a','b']]
#原始对象
c = copy.copy(a)#浅拷贝
print('a:',a,id(a),id(a[5]))#输出a的值,地址,子列表的地址
print('c:',c,id(c),id(c[5]))#输出c的值,地址,子列表的地址
a.append(6)
a[5].append('c')
print('a:',a,id(a),id(a[5]))#输出a的值,地址,子列表的地址
print('c:',c,id(c),id(c[5]))#输出c的值,地址,子列表的地址
"""
a: [1, 2, 3, 4, 5, ['a', 'b']] 2306922022208 2306922587200
c: [1, 2, 3, 4, 5, ['a', 'b']] 2306921998400 2306922587200
a: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6] 2306922022208 2306922587200
c: [1, 2, 3, 4, 5, ['a', 'b', 'c']] 2306921998400 2306922587200
"""
可以看出子列表元素的地址是一致的,其他元素不一致
不一致的不会受到源列表修改的影响
深拷贝
包含对象里面的子对象的地址的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变
import copy
a=[1,2,3,4,5,['a','b']]
#原始对象
d = copy.deepcopy(a)#深拷贝
print('a:',a,id(a),id(a[5]))#输出a的值,地址,子列表的地址
print('d:',d,id(d),id(d[5]))#输出d的值,地址,子列表的地址
a.append(6)
a[5].append('c')
print('a:',a,id(a),id(a[5]))#输出a的值,地址,子列表的地址
print('d:',d,id(d),id(d[5]))#输出d的值,地址,子列表的地址
"""
a: [1, 2, 3, 4, 5, ['a', 'b']] 1906091389952 1906091959104
d: [1, 2, 3, 4, 5, ['a', 'b']] 1906091374400 1906091544512
a: [1, 2, 3, 4, 5, ['a', 'b', 'c'], 6] 1906091389952 1906091959104
d: [1, 2, 3, 4, 5, ['a', 'b']] 1906091374400 1906091544512
"""
地址完全不一致