前言
本文主要介绍了python中容易面临的考试点和犯错点,即浅拷贝与深拷贝
首先,针对Python中的可变对象来说,例如列表,我们可以通过以下方式进行浅拷贝和深拷贝操作:
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a # 赋值,将变量a赋值给变量b
c = a.copy() # 浅拷贝, 或者 c = copy.copy(a)
d = copy.deepcopy(a) # 深拷贝
print(a) # [1, 2, 3, 4, ['a', 'b']]
print(b) # [1, 2, 3, 4, ['a', 'b']]
print(c) # [1, 2, 3, 4, ['a', 'b']]
print(d) # [1, 2, 3, 4, ['a', 'b']]
我们可以发现,赋值、浅拷贝和深拷贝后的变量的值是一样的,但他们的“内部”真的一样吗?
本文就是回答这个问题的
参考
本文主要参考了哔哩哔哩视频:十分钟!彻底弄懂Python深拷贝与浅拷贝机制
是视频里,up主推荐了一个神奇,即pythontutor
列表(list)
结论
为了探究前言中提到的a,b,c,d是个变量是否真的一样,我们借助pythontutor来进行可视化,从内存的角度来进行探究
结论:
赋值:变量b和a是完全一样的,即他们完全共享同一个内存空间,a变,b也会跟着变。
浅拷贝:变量c只有跟a共享第二级的列表,而不共享第一级列表的内容,即改变a的第一层列表内容,c不会变,而改变a第二层列表的内容,c就会跟着变了。
深拷贝:变量d和a完全不共享任何内存,d完全是新开辟了一个新的空间,即可认为d和a是完全没有关系的,改变a或者d都不会影响对方。
测试
import copy
a = [1, 2, 3, 4, ['a', 'b']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a) # [1, 2, 3, 4, ['a', 'b']]
print('b:', b) # [1, 2, 3, 4, ['a', 'b']]
print('c:', c) # [1, 2, 3, 4, ['a', 'b']]
print('d:', d) # [1, 2, 3, 4, ['a', 'b']]
a.append(5)
a[4].append('c')
print('a:', a) # [1, 2, 3, 4, ['a', 'b', 'c'], 5]
print('b:', b) # [1, 2, 3, 4, ['a', 'b', 'c'], 5]
print('c:', c) # [1, 2, 3, 4, ['a', 'b', 'c']]
print('d:', d) # [1, 2, 3, 4, ['a', 'b']]
结果:
这里的结果也不用多解释了,完全符合前面的结论
元组(tuple)
由于元组是不可变对象,那它的浅拷贝与深拷贝会一样吗?例如:
import copy
a = (1, 2, 3, 4, ('a', 'b'))
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a)
print('b:', b)
print('c:', c)
print('d:', d)
还是直接去看内存空间
结论:
对于元组来说,赋值、浅拷贝与深拷贝没有区别,都共享同一个内存,这也很好理解,因为元组是不可变对象,是无法对变量a进行修改的
列表与元组混合
列表里面嵌套元组
import copy
a = [1, 2, 3, 4, ('a', 'b')]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a)
print('b:', b)
print('c:', c)
print('d:', d)
内存情况:
结论:
就算是深拷贝,元组部分都是共享内存的
元组里面嵌套列表
import copy
a = (1, 2, 3, 4, ['a', 'b'])
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print('a:', a)
print('b:', b)
print('c:', c)
print('d:', d)
内存情况:
结论:
完全同列表的情况