lazyend 发表于 2020-5-21 13:18:26

字典的copy()相关疑问

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

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

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

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

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


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


这个copy()的机制我理解的是copy的字典或者列表等等不会因为原有列表/字典的改变而改变 那么为什么这里 dict2在特定情况下会跟随dict1改变呢?

Twilight6 发表于 2020-5-21 13:23:20

这个解释起来好麻烦{:10_245:}

永恒的蓝色梦想 发表于 2020-5-21 13:25:52

Twilight6 发表于 2020-5-21 13:23
这个解释起来好麻烦

确实。

hrp 发表于 2020-5-21 13:57:32

解释起来费口水…你只要知道字典copy方法复制的是字典本身,属于浅复制,本例子字典里面的值(列表)与用copy方法复制出来的字典里的值还是相同的地址。

没解释完,手机打字好费劲

Twilight6 发表于 2020-5-21 14:04:44

我去重新补补这节课,等下看下行不行来给你解释下哈哈

jinlovelive 发表于 2020-5-21 14:08:10

按照上面大佬的意思就是只复制了dict的表面对应关系,对应关系中key对应的内容list什么的仍然是复制的引用源

好鱼怕冷 发表于 2020-5-21 14:09:12

第一个,字典的问题:

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

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

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

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

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

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

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

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

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

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

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


heidern0612 发表于 2020-5-21 14:20:49

因为列表是可变类型,它属于在一层的基层上,间接又指向了另外一层。

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


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

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

lazyend 发表于 2020-5-21 14:29:31

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

那么是只有字典中的值是 列表才有这种现场吗? 还是有其他的情况也是这样子

lazyend 发表于 2020-5-21 14:30:35

好鱼怕冷 发表于 2020-5-21 14:09
第一个,字典的问题:




感谢解答 已经很厉害了啊   不过我比较不理解的是为什么其他例如元组 字符串之类的不会产生这种现象 而只有值是列表的时候会这样子

sunrise085 发表于 2020-5-21 14:39:44

本帖最后由 sunrise085 于 2020-5-21 14:51 编辑

这是深拷贝和浅拷贝的问题
若是单层可变类型对象,浅拷贝(copy())函数就可以搞定,所谓单层可变类型对象,是指可变类型对象的元素(键值)是不可变类型对象
若是多层可变类型对象,就必须用深拷贝(deepcopy())函数,所谓多层可变类型对象,是指可变类型对象的元素(键值)仍然是可变类型对象,就像你的这个dict1
看看这个帖子最后一部分。

lazyend 发表于 2020-5-21 14:43:30

我又根据回答研究了下 这个跟层数有关
list1=]
list2=list1.copy()
如果list1=5 则 list1 list2都会改变
但是如果我list1= 这样子list2并不会跟着改变   可能就是跟层数有关

lazyend 发表于 2020-5-21 14:46:26

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

感谢解答和分享内容对新手非常有帮助

青出于蓝 发表于 2020-5-21 14:56:27

学到了
页: [1]
查看完整版本: 字典的copy()相关疑问