Python浅拷贝和和深拷贝

Python提供了copy模块,用于对象的拷贝操作,包括copy和deepcopy两个函数,分别用于浅拷贝和深拷贝,以下分析两者的差异:

1. 父对象中包含可变对象

首先给出一个例子:

import copy

a = [1,2,3,['abc','def']]
b = a                    #对象引用
c = copy.copy(a)         #浅拷贝
d = copy.deepcopy(a)     #深拷贝

print ('修改前:')
print ('a = ', a)
print ('b = ', b)
print ('c = ', c)
print ('d = ', d)
print ()

print ('id(a)=', id(a))
print ('id(b)=', id(b))
print ('id(c)=', id(c))
print ('id(d)=', id(d))
print ()

a.append('a_app')         #向a附加新元素
a[3].append('sub_app')    #向a子列表附加新元素

print ('修改后:')
print ('a = ', a)
print ('b = ', b)
print ('c = ', c)
print ('d = ', d)
以上程序创建列表a,其中a[3]同样是个列表。

b为a的对象引用,c使用copy实现对a的浅拷贝,d使用deepcopy实现对a的深拷贝。

随后向a和a[3]中分别添加了新的元素'a_app'以及'sub_app'。

运行程序,输出结果如下:


可以看到:

(1) a和b完全为同一个东西,从id(a)==id(b)即可看出,a的操作将完全同步到b。

(2) c为a的浅拷贝,a操作不影响c,但a的子对象操作影响c。这是因为浅拷贝只是拷贝了父对象,没有拷贝子对象,c中子对象列表完全是a中子对象列表的引用。

(3) d为a的深拷贝,无论a的操作还是a的子对象的操作,对d均无影响。这是因为深拷贝对父对象和子对象均进行了操作,d中所有元素均是新创建的,与拷贝源a无任何关联。

2. 父对象中无可变对象

以上例子中,父对象a列表中包含新列表,为可变对象。当父对象中所有元素均为不可变对象时,情况又是怎样的?

import copy

lista = [1,2,3,4]
listb = copy.copy(lista)

print ('修改前:')
print ('lista = ', lista)
print ('listb = ', listb)
print ()

print ('id(lista) = ', id(lista))
print ('id(listb) = ', id(listb))
print ()

lista [1] = 100
print ('修改后:')
print ('lista = ', lista)
print ('listb = ', listb)
lista中所有元素均是不可变的,listb使用copy实现对lista的浅拷贝。

程序运行结果如下:


可见,对lista的操作并没有影响listb,listb虽是浅拷贝,但其对象及内容均是全新的。

3. 总结

(1) 浅拷贝和深拷贝都产生了一个新的对象,从拷贝后两者id不同可知。

(2) 浅拷贝内容并不是全新创建的,而是父对象的引用。

(3) 深拷贝无论对象还是内容都是全新的,拷贝完成后父对象任何修改均对其无任何影响。

(4) 以上说的的浅拷贝和深拷贝的差异,仅仅是在父对象中包含可变对象(如列表,字典等)时才成立。当父对象中所有对象元素都不可变时(如数字,字符串,元组等),两者并无差异,即使浅拷贝,其对象和内容都是全新生成的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值