求解,这段代码运行结果怎么跟我想的不同

2019-12-24 23:45:41 +08:00
 xjay

大概的代码是这样的

def run(data):
    s = []
    for c in ['ccc', 'ddd']:
        data['c'] = c
        print(data)
        s.append(data)

    print(s)

if __name__ == "__main__":
    run({'a': 'aaa', 'b': 'bbb'})

然后我想得到的结果是

{'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}
{'a': 'aaa', 'b': 'bbb', 'c': 'ddd'}
[{'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}, {'a': 'aaa', 'b': 'bbb', 'c': 'ddd'}]

但是结果却是

{'a': 'aaa', 'b': 'bbb', 'c': 'ccc'}
{'a': 'aaa', 'b': 'bbb', 'c': 'ddd'}
[{'a': 'aaa', 'b': 'bbb', 'c': 'ddd'}, {'a': 'aaa', 'b': 'bbb', 'c': 'ddd'}]

为什么?我的理解有错误吗?求解,我是被什么麻痹了?

3117 次点击
所在节点    Python
8 条回复
jxxz
2019-12-24 23:49:57 +08:00
引用传递
jxxz
2019-12-24 23:51:26 +08:00
append 的是两个相同的 data 字典对象,所以第二次 ddd 覆盖了第一次的 ccc
jugelizi
2019-12-24 23:51:53 +08:00
哈哈 这分词 bug
你应该看下变量在内存里如何存放的
melovto
2019-12-24 23:52:37 +08:00
函数传的是引用 改变了外部变量
wangyzj
2019-12-24 23:53:52 +08:00
list 不是副本
xjay
2019-12-25 00:32:28 +08:00
@jxxz @jugelizi @melovto @wangyzj 谢谢各位,我已经知道为什么了
CzaOrz
2019-12-25 09:58:26 +08:00
我也遇到过类似问题。并不是覆盖与被覆盖的关系,也不是引用了外部变量。
造成这种现象是因为 list 和 dict 都是可变对象,是一种容器,对象被创建后内容可修改。

在没有拷贝的前提下直接重复引用同一可变对像,结果多次引用都是指向的同一对象。
一旦对`容器`进行了某些修改,就自然会造成所有引用的改变。
(话说,还有一个浅拷贝和深拷贝的坑~)
xjay
2019-12-25 15:09:58 +08:00
@CzaOrz 谢谢,这个解释应该是最准确的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/632023

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX