我认为我的代码会更清晰 -
someList = list()
foo = {'a':'b'}
someList.append(foo)
print someList
>>> [{'a':'b'}]
defaultbazz = {'a':2, 'b':'t', 'c':'gg'}
for k, v in defaultbazz.iteritems():
foo[k] = v
print someList
>>> [{'a': 2, 'c': 'gg', 'b': 't'}]
最后一次打印不应该是[{'a':'b'}]
吗?我没有更新someList
,我希望它原样..
在我看来,这是一种未被解释的行为。
但如果这就是python的工作方式,我该如何找到解决方法?即使设置一个新的dict也会更新原来的dict ..我的意思是:
someList = list()
foo = {'a':'b'}
someList.append(foo)
print someList
>>> [{'a':'b'}]
bar = foo
defaultbazz = {'a':2, 'b':'t', 'c':'gg'}
for k, v in defaultbazz.iteritems():
bar[k] = v
print someList
>>> [{'a': 2, 'c': 'gg', 'b': 't'}]
如果有人能解释我为何会发生这种情况,我将感激不尽。
答案 0 :(得分:11)
当你将dict添加到列表或将其分配给新变量时,看起来你期望复制你的dict,但这不是Python的运作方式。如果你指定一个字典 - 实际上,如果你指定任何一个对象 - 你不是在创建一个新对象,而是只是给你的对象一个新的名字。 (一个对象可以有多个名称。)
因此,当您使用新名称编辑对象时,该对象的单个实例会更改,并且当您通过任何名称访问该对象时,该更改都是可见的。
如果要复制对象,则可以执行以下操作:
bar = dict(foo)
或
bar = foo.copy()
答案 1 :(得分:5)
简化:
a = {2: 3}
b = [a]
b
包含a
的“引用”(并且是dict
,它是可变的) - 因此,如果a
被修改,则通过a
访问b
列表a
将显示修改后的a
。
您必须明确创建b = [dict(a)]
的副本,在这种情况下可以这样做:
copy
但您应该查看copy.copy()
和copy.deepcopy()
答案 2 :(得分:3)
答案 3 :(得分:2)
Python中的变量只是对象的名称。如果您将对象从“附加”的任何名称更改为它,您将看到每个其他名称的更改。 Python从不为您自动创建副本,特别是:
someList.append(foo)
没有创建foo
的副本并将其放在someList
上,它会在对象附加名称 {{1} }指的是列表。
您可以为此对象创建第二个名称
foo
但这也不会创建副本。特别是
bar = foo
和
foo['x'] = 42
然后将在完全相同的对象上运行。您可以通过打印对象的内存地址来验证这一点:
bar['x'] = 42
并且看到它们是相同的。
如果您需要Python中的副本,则需要明确创建一个副本。根据您的需要,print id(foo), id(bar)
模块 - copy
或copy.copy()
- 可以满足您的需求:
copy.deepcopy()
现在应该打印不同的内存位置。
答案 4 :(得分:1)
Dicts是可变的,这意味着它们可以改变。这是因为foo
位于someList
内,而您在foo
中正在更改for-loop
。看看这个简单的例子:
a_dict = {'a':'b'}
a_list = [a_dict]
print a_list # [{'a':'b'}]
#change the dict
a_dict['a'] = 'c'
print a_list # [{'a':'c'}]