概述
此概念容易在面试笔试中问到
本文针对的数据类型是list、set、dict等可变数据类型,其他数据类型在本文中意义不大
赋值
观察且执行下面代码:
l=[1,2,3]
l2=l
l.append(4)
print(id(l))
print(id(l2))
print(l)
print(l2)
结果如下:
50178288
50178288
[1, 2, 3, 4]
[1, 2, 3, 4]
像l2=l这种直接赋值,l和l2的引用指向 同一个内存地址,所以当改变l的值,l2也跟着改变
copy浅拷贝
观察且执行下面代码
import copy
l=[1,3.14,[2,4,6]]
l2=copy.copy(l)
print(l)
print(l2)
print(id(l))
print(id(l2))
结果如下:
[1, 3.14, [2, 4, 6]]
[1, 3.14, [2, 4, 6]]
8563088
8580432
执行代码l2=copy.copy(l)后,两个变量的 内容一样,但是两个变量的引用指向 不同的地址
继续编码,并观察执行结果
l.append('python')
print(l)
print(l2)
结果如下:
[1, 3.14, [2, 4, 6], 'python']
[1, 3.14, [2, 4, 6]]
因为两个变量的引用指向 不同的地址,所以一个list追加元素,另一个list不会改变
list内元素的地址
继续编码,分别查看每个list的元素的地址
for item in l:
print(id(item),end=',')
print()
for item in l2:
print(id(item),end=',')
执行结果如下:
1616306960,52857232,52865544,
1616306960,52857232,52865544,
两个list内的元素地址相同
继续编码,并观察执行结果
l[2].append(8)
print(l)
print(l2)
打印的结果是否相同
总结
copy浅拷贝的特点:
- 浅拷贝后,两个序列的 内存地址 不同
- 两个序列 相同索引 的 元素 的 内存地址 相同
深拷贝
观察且执行下面代码
import copy
l=[1,3.14,[2,4,6],'python']
l2=copy.deepcopy(l)
print(l)
print(l2)
print(id(l))
print(id(l2))
结果如下:
[1, 3.14, [2, 4, 6], 'python']
[1, 3.14, [2, 4, 6], 'python']
9087376
9104920
执行代码l2=copy.deepcopy(l)后,两个变量的 内容一样,但是两个变量的引用指向 不同的地址
继续编码,并观察执行结果
l.append('深拷贝')
print(l)
print(l2)
结果如下:
[1, 3.14, [2, 4, 6], 'python','深拷贝']
[1, 3.14, [2, 4, 6], 'python']
因为两个变量的引用指向 不同的地址,所以一个list追加元素,另一个list不会改变
list内元素的地址
观察执行下面的代码,深拷贝后,分别打印每个list内元素的地址
l=[1,3.14,'python',(1,2),[2,4,6],{3,4,5}]
l2=copy.deepcopy(l)
for item in l:
print(id(item),end=',')
print()
for item in l2:
print(id(item),end=',')
执行结果如下:
1616306960,52595088,52109792,52620864,52603400,52607616,
1616306960,52595088,52109792,52620864,52621144,52607856,
两个list内的元素 地址:
- 如果元素是数字、字符串、tuple等 不可变数据类型,地址相同
- 如果元素是list、set等 可变数据类型,地址不同
继续编码,并观察执行结果
l[2].append(8)
print(l)
print(l2)
打印的结果是否相同
总结
copy深拷贝的特点:
- 深拷贝的两个序列的 内存地址 不同
- 如果内部元素是 int、float、str、bool、tuple 等 不可变数据类型,内存地址 相同
- 如果内部元素是 list、set、dict 等 可变数据类型,内存地址 不同