首页 / 知识
Python浅拷贝和深度拷贝
2023-11-12 13:39:00
前面介绍了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相关知识,请关注我们http://www.mobiletrain.org/
最新内容
相关内容
用Python爬取百度搜索结果
用Python爬取百度搜索结果,百度,项目,分析,软件,网址,广告,时间,培训,粮食,标题,一、前言众所周知,百度上直接搜索关键字会出来一大堆东西,时常优化 Python 程序的内存占用
优化 Python 程序的内存占用,代码,数据,情况,培训,对象,字典,内存,垃圾,程序,机制,Python的垃圾回收机制通过引用计数来决定一个对象要不要被Python变量数据类型的转换
Python变量数据类型的转换,代码,数据,培训,信息,字符串,类型,变量,整数,浮点,函数,虽然Python是弱类型编程语言,不需要像Java或C语言那样还要Python变量的类型(弱类型语言)
Python变量的类型(弱类型语言),检测,代码,数据,培训,类型,变量,语言,赋值,数字型,字符串,在强类型的编程语言中,定义变量时要指明变量的类型,而列举Python面向对象中带双下划线的
列举Python面向对象中带双下划线的特殊方法,信息,代码,培训,对象,属性,方法,实例,字符串,里边,内容,__new__:生成实例__init__:生成实例的属性_Python面向对象的基本概念
Python面向对象的基本概念,概念,信息,位置,新增,培训,属性,鸟类,定义,对象,方法,python使用类(class)和对象(object),进行面向对象(object-oriPython生成表达式和列表解析
Python生成表达式和列表解析,工具,培训,列表,表达式,生成器,嵌套,计算所,元素,两个,动作,生成器表达式(Generatorexpression)和列表解析(ListPython 条件对象
Python 条件对象,状态,培训,对象,条件,线程,方法,底层,发生,场景,典型,条件对象总是与某种类型的锁对象相关联,锁对象可以通过传入获得,或者在Python 事件对象
Python 事件对象,通信,培训,线程,事件,对象,内部,标志,信号,机制,以上,一个线程发出事件信号,其他线程等待该信号,这是最简单的线程之间通信机Python之什么是面向对象?
Python之什么是面向对象?,设计,流程,代码,个体,大唐,对比,培训,模子,上帝,对象,OOP(ObjectOrientedPrograming)编程是利用“类”和“对象”来python 列表元素的删除
python 列表元素的删除,代码,数据,位置,连续,异常,首次,培训,元素,列表,空隙,使用del命令删除列表中的指定位置上的元素。>>>a_list=[3,5,7,9python 列表元素访问与计数
python 列表元素访问与计数,异常,首次,培训,列表,元素,下标,对象,方法,次数,以上,使用下标直接访问列表元素,如果指定下标不存在,则抛出异常。>