1,深拷贝和浅拷贝只相对于容器类型的对象(compound obejects)来说,对于原子类型的对象(atomic s)没有这个概念。看下面的代码:
num = 123
num_c = num
print(id(num), id(num_c))
num_c = 456
print(id(num), id(num_c))
# 输出为
# 4526750784 4526750784
# 4526750784 4563542224
string = \'abc\'
string_c = string
print(id(string), id(string_c))
string_c = \'def\'
print(id(string), id(string_c))
# 输出为
# 4528361176 4528361176
# 4528361176 4529762464
对于原子类型,赋值(assignment)只是创建了一个引用指向另一个对象,改变其中一个对象不会影响另一个对象。
2,对于容器对象,正常赋值(normal assignment)和切片赋值(slice assignment)效果不一样。代码如下:
lis = [\'a\', \'b\', \'c\']
lis_c = lis
print(id(lis), id(lis_c))
[print(x, id(x)) for x in lis]
[print(x, id(x)) for x in lis_c]
print(\'After\')
lis_c[1:3] = [\'d\', \'e\']
print(id(lis), id(lis_c))
[print(x, id(x)) for x in lis]
[print(x, id(x)) for x in lis_c]
# 输出为
4564651592 4564651592
a 4528834072
b 4528276568
c 4528219168
a 4528834072
b 4528276568
c 4528219168
After
4564651592 4564651592
a 4528834072
d 4528456400
e 4528388952
a 4528834072
d 4528456400
e 4528388952
lis = [\'a\', \'b\', \'c\']
lis_c = lis[:]
print(id(lis), id(lis_c))
[print(x, id(x)) for x in lis]
[print(x, id(x)) for x in lis_c]
print(\'After\')
lis_c[1:3] = [\'d\', \'e\']
print(id(lis), id(lis_c))
[print(x, id(x)) for x in lis]
[print(x, id(x)) for x in lis_c]
# 输出为
4564225608 4564496008
a 4528834072
b 4528276568
c 4528219168
a 4528834072
b 4528276568
c 4528219168
After
4564225608 4564496008
a 4528834072
b 4528276568
c 4528219168
a 4528834072
d 4528456400
e 4528388952
lis = [\'a\', \'b\', \'c\']
lis_c = lis
print(id(lis), id(lis_c))
[print(x, id(x)) for x in lis]
[print(x, id(x)) for x in lis_c]
print(\'After\')
lis_c = [\'d\', \'e\', \'f\']
print(id(lis), id(lis_c))
[print(x, id(x)) for x in lis]
[print(x, id(x)) for x in lis_c]
# 输出为
4562685000 4562685000
a 4528834072
b 4528276568
c 4528219168
a 4528834072
b 4528276568
c 4528219168
After
4562685000 4564494984
a 4528834072
b 4528276568
c 4528219168
d 4528456400
e 4528388952
f 4527690168
可以看出,正常赋值lis_c和lis指向同样的内存地址。对于正常赋值,改变lis_c的部分元素,lis的元素也会跟着改变;而对于切片赋值,二者指向不同的地址,所以不会相互影响。对正常赋值,如果改变整个lis_c中的元素,则lis_c的内存地址会发生改变,所以lis_c和lis不会相互影响。
3,字典的性质与列表相似,具有2中的性质,改变字典部分的key或全部的key,字典的内存地址会变;改变部分的value或全部的value,字典的内存地址不变。
dic = {\'a\': 1, \'b\': 2, \'c\': 3}
dic_c = dic
print(id(dic), id(dic_c))
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic.items()]
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic_c.items()]
print(\'change part of key\')
dic_c = {\'aa\': 1, \'bb\': 2, \'c\': 3}
print(id(dic), id(dic_c))
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic.items()]
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic_c.items()]
# 输出为
4564146576 4564146576
key: a 4528834072 value: 1 4526746880
key: b 4528276568 value: 2 4526746912
key: c 4528219168 value: 3 4526746944
key: a 4528834072 value: 1 4526746880
key: b 4528276568 value: 2 4526746912
key: c 4528219168 value: 3 4526746944
change part of key
4564146576 4564735176
key: a 4528834072 value: 1 4526746880
key: b 4528276568 value: 2 4526746912
key: c 4528219168 value: 3 4526746944
key: aa 4550712208 value: 1 4526746880
key: bb 4543935296 value: 2 4526746912
key: c 4528219168 value: 3 4526746944
dic = {\'a\': 1, \'b\': 2, \'c\': 3}
dic_c = dic
print(id(dic), id(dic_c))
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic.items()]
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic_c.items()]
print(\'change all values\')
dic_c[\'a\'] = 11
dic_c[\'b\'] = 22
dic_c[\'c\'] = 33
print(id(dic), id(dic_c))
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic.items()]
[print(\'key:\', x, id(x), \'value:\', y, id(y)) for x, y in dic_c.items()]
# 输出为
4564735320 4564735320
key: a 4528834072 value: 1 4526746880
key: b 4528276568 value: 2 4526746912
key: c 4528219168 value: 3 4526746944
key: a 4528834072 value: 1 4526746880
key: b 4528276568 value: 2 4526746912
key: c 4528219168 value: 3 4526746944
change all values
4564735320 4564735320
key: a 4528834072 value: 11 4526747200
key: b 4528276568 value: 22 4526747552
key: c 4528219168 value: 33 4526747904
key: a 4528834072 value: 11 4526747200
key: b 4528276568 value: 22 4526747552
key: c 4528219168 value: 33 4526747904
4,对于元祖来说,改变其中一个元素,就使整个元祖的内存地址发生改变。
tup = (\'a\', \'b\', [\'c\', \'d\'])
tup_c = tup
print(id(tup), id(tup_c))
[print(x, id(x)) for x in tup]
[print(x, id(x)) for x in tup_c]
print(\'After\')
tup_c = (\'a\', \'b\', [\'c\', \'e\'])
print(id(tup), id(tup_c))
[print(x, id(x)) for x in tup]
[print(x, id(x)) for x in tup_c]
# 输出为
4564433872 4564433872
a 4528834072
b 4528276568
[\'c\', \'d\'] 4564658312
a 4528834072
b 4528276568
[\'c\', \'d\'] 4564658312
After
4564433872 4564147008
a 4528834072
b 4528276568
[\'c\', \'d\'] 4564658312
a 4528834072
b 4528276568
[\'c\', \'e\'] 4564603272
5,通过下面三种方法可以建立浅拷贝: (1) taking a complete slice [:], (2) using a factory function, e.g., list(), dict(), etc., or (3) using the copy() function of the copy module。深拷贝要用到copy module中的copy.deepcopy()。
import copy
a = [\'123\', \'456\', [\'a\', \'b\']]
b = copy.copy(a)
print(id(a), id(b))
b[2][0] = [\'d\']
print(a, id(a), b, id(b))
# 输出为
4564727816 4564602952
[\'123\', \'456\', [[\'d\'], \'b\']] 4564727816 [\'123\', \'456\', [[\'d\'], \'b\']] 4564602952
import copy
a = [\'123\', \'456\', [\'a\', \'b\']]
b = copy.deepcopy(a)
print(id(a), id(b))
b[2][0] = [\'d\']
print(a, id(a), b, id(b))
# 输出为
4564493896 4564658824
[\'123\', \'456\', [\'a\', \'b\']] 4564493896 [\'123\', \'456\', [[\'d\'], \'b\']] 4564658824
可以看出,无论浅拷贝还是深拷贝,list在赋值前后的内存地址不一样,不同点是深拷贝会递归地为容器中的容器进行拷贝;浅拷贝只对最外层拷贝,内层的容器还是指向同一个地址,会相互影响。
继续阅读与本文标签相同的文章
下一篇 :
Trie树的实现
-
曾经风靡一时的360安全卫士为什么如今没落了?
2026-05-18栏目: 教程
-
用C语言编程,如何节省存储空间?
2026-05-18栏目: 教程
-
三元牛奶,的优势在哪里?
2026-05-18栏目: 教程
-
常浏览“成人网站”要留意了,有这2种反应,请立马关闭
2026-05-18栏目: 教程
-
美国SpaceX公司计划向太空发射4.2万枚通信卫星
2026-05-18栏目: 教程
