Python复制方法“=/copy/deepcopy”的区别

1、当复制的值是不可变对象(数值,字符串,元组)时,=/copy/deepcopy三者没有区别。

测试代码:

import copy

a = 'abcdefgh'
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

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

a += 'x'  #相当于重新赋值,把a这个标签重新贴到了一个新的箱子

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

输出结果:

abcdefgh abcdefgh abcdefgh abcdefgh
2239009875184 2239009875184 2239009875184 2239009875184
abcdefghx abcdefgh abcdefgh abcdefgh
2239007676720 2239009875184 2239009875184 2239009875184

总结:复制后,=/copy/deepcopy的id不变。改变原对象的内容,不会改变新对象的内容。但是,原对象的id会改变。

2、当复制的值是可变对象(列表,字典)时,当重新给原对象赋值时,=/copy/deepcopy三者没有区别。

测试代码:

import copy
a = [1,2,3,4]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

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

a = [5,6,7,8] #重新赋值,相当于把a这个标签重新贴到了一个新的箱子

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

输出结果:

[1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4]
2239009923464 2239009923464 2239010021896 2239010023112
[5, 6, 7, 8] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4]
2239008566984 2239009923464 2239010021896 2239010023112

总结:复制后,=的id不会变,copy和deepcopy的id会变。给原对象重新赋值,不会改变=/copy/deepcopy新对象的内容。但是,原对象的id会变,=/copy/deepcopy的id不变。

测试代码:

import copy
a = [1,2,3,4]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

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

a[0], a[1], a[2], a[3] = 5, 6, 7, 8  #直接在原列表上修改,相当于把有标签的箱子内容换了
 
print(a,b,c,d)
print(id(a),id(b),id(c),id(d))

输出结果:

[1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4]
2239009809608 2239009809608 2239010021768 2239009849160
[5, 6, 7, 8] [5, 6, 7, 8] [1, 2, 3, 4] [1, 2, 3, 4]
2239009809608 2239009809608 2239010021768 2239009849160

总结:复制后,=的id不会变,copy和deepcopy的id会变。改变原对象的内容,=的新对象随之改变,但copy/deepcopy新对象的内容不会改变。原对象和=/copy/deepcopy的id不变。

3、当复制的值是可变对象(列表,字典)时,当改变的值是不可变子对象时,=/copy/deepcopy三者有区别。

测试代码:

import copy
a = [1,2,3,4]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

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

a.append(5)  #不是重新赋值,是直接修改

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

输出结果:

[1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, 3, 4]
2239009846728 2239009846728 2239009879432 2239009964680
[1, 2, 3, 4, 5] [1, 2, 3, 4, 5] [1, 2, 3, 4] [1, 2, 3, 4]
2239009846728 2239009846728 2239009879432 2239009964680

总结:复制后,=的id不会变,改变原对象的内容,新对象的内容随之改变。复制后,copy和deepcopy的id会变,改变原对象的内容,不会改变新对象的内容。

4、当复制的值是可变对象(列表,字典)时,当改变的值是不可变子对象时,=/copy/deepcopy三者有区别。改变的值是可变子对象时,还有进一步的区别。

测试代码:

import copy
list1=[['good','bad'],1,2]
list2=list1
list3=copy.copy(list1)
list4=copy.deepcopy(list1)

print(id(list1))
print(id(list2))
print(id(list3))
print(id(list4))

list1[0].append('medium')

print(list1)
print(list2)
print(list3)
print(list4)

print(id(list1))
print(id(list2))
print(id(list3))
print(id(list4))

list1.append(3)

print(list1)
print(list2)
print(list3)
print(list4)

print(id(list1))
print(id(list2))
print(id(list3))
print(id(list4))

输出结果:

2239009790792
2239009790792
2239009790536
2239009881864
[['good', 'bad', 'medium'], 1, 2]
[['good', 'bad', 'medium'], 1, 2]
[['good', 'bad', 'medium'], 1, 2]
[['good', 'bad'], 1, 2]
2239009790792
2239009790792
2239009790536
2239009881864
[['good', 'bad', 'medium'], 1, 2, 3]
[['good', 'bad', 'medium'], 1, 2, 3]
[['good', 'bad', 'medium'], 1, 2]
[['good', 'bad'], 1, 2]
2239009790792
2239009790792
2239009790536
2239009881864

总结:复制后,=的id不会变,改变原对象的内容,新对象的内容随之改变。复制后,deepcopy的id会变,改变原对象的内容,不会改变新对象的内容。复制后,deepcopy的id会变,内容是否会变,分为两种情况:1)如果改变的内容是可变子对象,则新对象的内容随之改变;2)如果改变的内容是不可变子对象,则新对象的内容不会改变。

综上所述,有以下结论:
1、对于数值、字符串和元组,不同的复制方式没有区别,复制后,=/copy/deepcopy的id不变。改变原对象的内容,不会改变新对象的内容。
2、对于数值、字符串和元组,只能通过赋值来修改这些对象,修改后id会发生变化。对于列表和字典这些可变对象,可以通过赋值来修改这些对象,修改后id会发生变化;也可以通过直接修改对象的内容,修改后id不会发生变化。
3、deepcopy才是真正意义上的复制了一个独立的对象,复制后,id会变,内容不会随着原对象的变化而变化。
4、可以把列表和字典这些可变对象看作箱子。b=a可以理解成标签b贴到有标签a的箱子上面,所以如果重新给a赋值,就相当于把标签a贴到了一个新箱子上,a的id自然就变了,但是b的id和内容都不变。如果是直接修改a,则相当于在修改箱子的内容,所以b的id不会变,但是内容却跟着变了。
5、copy是假的复制。复制后,id会变。但是,针对列表和字典这些可变对象,其内容变化分情况:在可变子对象变化时,会随之变化;在不可变子对象变化时,不会随之变化。

详细解释参考:https://blog.csdn.net/u011630575/article/details/78604226

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值