鱼C论坛

 找回密码
 立即注册
查看: 953|回复: 13

[已解决]字典的copy()相关疑问

[复制链接]
发表于 2020-5-21 13:18:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 lazyend 于 2020-5-21 13:21 编辑

我研究了半天还是没搞定下面这个机制是什么 有没有大神帮我解答下

dict1= {1:['a','b'],2:['c','d']}
dict2=dict1.copy()

在这里如果我
dict1[1][0] = 'nihao'
那么
dict1和dict2都会变成 {1:['nihao','b'],2:['c','d']}

但是如果我
dict1[1] = {'nihao','b'}
那么只有 dict1 key 1的值会变 dict2的值不会变
而且如果我dict1.popitem()  dict2的也不会变  那么为什么只有当 dict1[1][0]这种情况下  dict2的value也会跟着改变呢?


列表也是
list1=[0,1]
list2=list1.copy()
无论List1 pop append 还是 list1[0]=100改变 list2都不会随之改变   


这个copy()的机制我理解的是copy的字典或者列表等等不会因为原有列表/字典的改变而改变 那么为什么这里 dict2在特定情况下会跟随dict1改变呢?
最佳答案
2020-5-21 14:39:44
本帖最后由 sunrise085 于 2020-5-21 14:51 编辑

这是深拷贝和浅拷贝的问题
若是单层可变类型对象,浅拷贝(copy())函数就可以搞定,所谓单层可变类型对象,是指可变类型对象的元素(键值)是不可变类型对象
若是多层可变类型对象,就必须用深拷贝(deepcopy())函数,所谓多层可变类型对象,是指可变类型对象的元素(键值)仍然是可变类型对象,就像你的这个dict1
看看这个帖子最后一部分。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-5-21 13:23:20 | 显示全部楼层
这个解释起来好麻烦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 13:25:52 | 显示全部楼层
Twilight6 发表于 2020-5-21 13:23
这个解释起来好麻烦

确实。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 13:57:32 From FishC Mobile | 显示全部楼层
解释起来费口水…你只要知道字典copy方法复制的是字典本身,属于浅复制,本例子字典里面的值(列表)与用copy方法复制出来的字典里的值还是相同的地址。

没解释完,手机打字好费劲
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 14:04:44 | 显示全部楼层
我去重新补补这节课,等下看下行不行来给你解释下哈哈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 14:08:10 | 显示全部楼层
按照上面大佬的意思就是只复制了dict的表面对应关系,对应关系中key对应的内容list什么的仍然是复制的引用源
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 14:09:12 | 显示全部楼层
第一个,字典的问题:

dict1= {1:['a','b'],2:['c','d']}
dict2=dict1.copy()

在这里如果我
dict1[1][0] = 'nihao'
那么
dict1和dict2都会变成 {1:['nihao','b'],2:['c','d']}

>>> d1 = {1:['a', 'b'], 2:['c', 'd']}
>>> d2 = d1.copy()
>>> id(d1[1])
2650545373248
>>> id(d2[1])
2650545373248
>>> id(d1[1][0])
2650536230512
>>> id(d2[1][0])
2650536230512
>>> d1[1][0] = 'nihao'
>>> print(d1)
{1: ['nihao', 'b'], 2: ['c', 'd']}
>>> print(d2)
{1: ['nihao', 'b'], 2: ['c', 'd']}
>>> id(d1[1][0])
2650545611824
>>> id(d2[1][0])
2650545611824

list和dict都是可变数据类型,而且位置可索引,所以修改值不会引起地址指向的改变。

但是如果我
dict1[1] = {'nihao','b'}
那么只有 dict1 key 1的值会变 dict2的值不会变

>>> d1[1] = {'nihao', 'b'}
>>> id(d1[1])
2650545262368
>>> id(d2[1])
2650545373248
>>> id(d1)
2650545030848
>>> id(d2)
2650545139328
>>> 

后来,你将dict1 key 1 的值修改为一个集合类型的数据,由于数据类型的改变,内存就必须要开辟一块新的储存空间来存放新的集合数据。

可以发现,两个字典指向的地址已经不一样了。赋值给新类型数据的前后,dict1 key 1 的位置也不一样了。而dict1 key 1的地址却没有改变。

既然这时候两个字典已经被分配了不同的地址,再去做其他操作的时候,就不会相互影响了。所以也就有下面的:

而且如果我dict1.popitem()  dict2的也不会变  那么为什么只有当 dict1[1][0]这种情况下  dict2的value也会跟着改变呢?


新手上路:如有不妥,请指正,轻喷!


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2020-5-21 14:20:49 | 显示全部楼层
因为列表是可变类型,它属于在一层的基层上,间接又指向了另外一层。

就这么简单,copy只能复制一层,没办法复制两层,复制两层的话,需要深拷贝。


浅拷贝的话,不管什么类型都识别为不可变类型。

而深拷贝的话,识别了可变类型,这就是深拷贝和浅拷贝的区别。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-21 14:29:31 | 显示全部楼层
hrp 发表于 2020-5-21 13:57
解释起来费口水…你只要知道字典copy方法复制的是字典本身,属于浅复制,本例子字典里面的值(列表)与用copy ...

那么是只有字典中的值是 列表才有这种现场吗? 还是有其他的情况也是这样子
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-21 14:30:35 | 显示全部楼层
好鱼怕冷 发表于 2020-5-21 14:09
第一个,字典的问题:

感谢解答 已经很厉害了啊   不过我比较不理解的是为什么其他例如元组 字符串之类的不会产生这种现象 而只有值是列表的时候会这样子
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 14:39:44 | 显示全部楼层    本楼为最佳答案   
本帖最后由 sunrise085 于 2020-5-21 14:51 编辑

这是深拷贝和浅拷贝的问题
若是单层可变类型对象,浅拷贝(copy())函数就可以搞定,所谓单层可变类型对象,是指可变类型对象的元素(键值)是不可变类型对象
若是多层可变类型对象,就必须用深拷贝(deepcopy())函数,所谓多层可变类型对象,是指可变类型对象的元素(键值)仍然是可变类型对象,就像你的这个dict1
看看这个帖子最后一部分。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-21 14:43:30 | 显示全部楼层
我又根据回答研究了下 这个跟层数有关
list1=[1,2,[3,4]]
list2=list1.copy()
如果list1[2][0]=5 则 list1 list2都会改变
但是如果我list1[2]=[5,4] 这样子  list2并不会跟着改变   可能就是跟层数有关
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-5-21 14:46:26 | 显示全部楼层
sunrise085 发表于 2020-5-21 14:39
这是深拷贝和浅拷贝的问题
若是单层可变类型对象,浅拷贝(copy())函数就可以搞定,所谓单层可变类型对象, ...

感谢解答和分享内容  对新手非常有帮助
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-21 14:56:27 | 显示全部楼层
学到了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-21 02:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表