Python浅拷贝和深度拷贝
前面介绍了Python的赋值(对象的引用传递),那么Python如何解决原始数据在函数传递后不受影响呢,Python提供了浅度拷贝(shallowcopy)和深度拷贝(deepcopy)两种方式。
·浅拷贝(copy):拷贝父对象,不拷贝对象内部的子对象。
·深拷贝(deepcopy):完全拷贝了父对象及其子对象。
浅拷贝
1.不可变数据类型
下面对不可变对象整型变量和元组进行浅拷贝:
importcopy
a=1
b=copy.copy(a)
print(id(a))
print(id(b))
print(a==b)
print(aisb)
t1=(1,2,3)
t2=tuple(t1)
print(id(t1))
print(id(t2))
print(t1==t2)
print(t1ist2)
执行结果:
50622072
50622072
True
True
55145384
55145384
True
True
不可变对象的拷贝和对象的引用传递一样,a、b指向相同的对象,修改其中一个变量的值不会影响另外的变量,会开辟新的空间。
2.可变数据类型
对可变对象list进行浅拷贝:
importcopy
l1=[1,2,3]
l2=list(l1)
l3=copy.copy(l1)
l4=l1[:]
print(id(l1))
print(id(l2))
print(l1==l2)
print(l1isl2)
print(id(l3))
print(id(l4))
l1.append(4)
print(id(l1))
print(l1==l2)
print(l1isl2)
执行结果:
48520904
48523784
True
False
48523848
48521032
48520904
False
False
可以看到,对可变对象的浅拷贝会重新分配一块内存,创建一个新的对象,里面的元素是原对象中子对象的引用。改变l1的值不会影响l2,l3,l4的值,它们指向不同的对象。
上面的例子比较简单,下面举一个相对复杂的数据结构:
importcopy
l1=[[1,2],(4,5)]
l2=copy.copy(l1)
print(id(l1))
print(id(l2))
print(id(l1[0]))
print(id(l2[0]))
l1.append(6)
print(l1)
print(l2)
l1[0].append(3)
print(l1)
print(l2)
执行结果:
1918057951816
1918057949448
2680328991496
2680328991496
[[1,2],(4,5),6]
[[1,2],(4,5)]
[[1,2,3],(4,5),6]
[[1,2,3],(4,5)]
l2是l1的浅拷贝,它们指向不同的对象,因为浅拷贝里的元素是对原对象元素的引用,因此l2中的元素和l1指向同一个列表和元组对象(l1[0]和l2[0]指向的是相同的地址)。l1.append(6)不会对l2产生任何影响,因为l2和l1作为整体是两个不同的对象,不共享内存地址。
l1[0].append(3)对l1中的第一个列表新增元素3,因为l2是l1的浅拷贝,l2中的第一个元素和l1中的第一个元素,共同指向同一个列表,因此l2中的第一个列表也会相对应的新增元素3。
这里提一个小问题:如果对l1中的元组新增元素(l1[1]+=(7,8)),会影响l2吗?
到这里我们知道使用浅拷贝可能带来的副作用,要避免它就得使用深度拷贝。
深度拷贝
深度拷贝会完整地拷贝一个对象,会重新分配一块内存,创建一个新的对象,并且将原对象中的元素以递归的方式,通过创建新的子对象拷贝到新对象中。因此,新对象和原对象没有任何关联,也就是完全拷贝了父对象及其子对象。
importcopy
l1=[[1,2],(4,5)]
l2=copy.deepcopy(l1)
print(id(l1))
print(id(l2))
l1.append(6)
print(l1)
print(l2)
l1[0].append(3)
print(l1)
print(l2)
执行结果:
3026088342280
3026088342472
[[1,2],(4,5),6]
[[1,2],(4,5)]
[[1,2,3],(4,5),6]
[[1,2],(4,5)]
可以看到,l1变化不影响l2,l1和l2完全独立,没有任何联系。
在进行深度拷贝时,深度拷贝deepcopy中会维护一个字典,记录已经拷贝的对象与其ID。如果字典里已经存储了将要拷贝的对象,则会从字典直接返回。
以上内容为大家介绍了Python浅拷贝和深度拷贝,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。http://www.mobiletrain.org/
相关推荐HOT
更多>>python为什么不显示none
下面是关于Python中None的一些解释:None是一个特殊的常量。None和False不同。None不是0。None不是空字符串。None和任何其他的数据类型比较永远...详情>>
2023-11-06 20:39:22python怎样计算函数的返回值
python中,用def语句创建函数时,可以用return语句指定应该返回的值,该返回值可以是任意类型。需要注意的是,return语句在同一函数中可以出现...详情>>
2023-11-06 20:04:03python如何读取列表中元素的位置?
python读取列表中元素位置的方法:1、使用index()方法获取列表中指定元素的位置index()方法语法:str.index(str,beg=0,end=len(string))参数str...详情>>
2023-11-06 17:40:38Python中常见的字符串拼接方法有哪些?
针对大家在Python中常常遇到字符串拼接的问题,本文主要向大家介绍Python中常见的六种拼接方法:加号法、逗号法、直接拼接法、格式化法、join函...详情>>
2023-11-06 16:42:10