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