【问题标题】:When two dictionaries are instantiated together, updating one affects the other. Why?当两个字典一起实例化时,更新一个会影响另一个。为什么?
【发布时间】:2020-05-18 18:06:24
【问题描述】:

对不起,如果这个问题之前已经发布过,但我找不到答案。
当字典实例化如下:

foo = bar = {'a': 0}

foo = {'a':0}
bar = foo

更新一个字典会影响另一个:

foo['a'] += 1
print(foo)
// {'a': 1}
print(bar)
// {'a': 1}

然而当它们分别被实例化时:

foo = {'a':0}
bar = {'a':0}

foo['a'] += 1
print(foo)
// {'a':1}
print(bar)
// {'a':0}

但是,当以类似方式实例化变量时:

foo = bar = 0
foo += 1
print(foo)
// 1
print(bar)
// 0

首先,这里发生了什么?设置的变量是否等于同一个字典对象?
其次,如何将字典复制到另一个变量并更新第二个变量而不影响第一个变量?例如,我正在尝试将类似的字典附加到列表中,但更改了一个键值:

dic = {"foo":0,"bar":1}
list1 = [1,2,3,4]
list2 = []
for num in list1:
     temp = dic
     temp["bar"] = num
     list2.append(temp)
print(list2)
// [{"foo":0,"bar":4},{"foo":0,"bar":4},{"foo":0,"bar":4},{"foo":0,"bar":4}]

在此示例中,改为执行以下操作相当容易:

list1 = [1,2,3,4]
list2 = []
for num in list1:
     list2.append({'foo':0,'bar':num})
print(list2)
// [{"foo":0,"bar":1},{"foo":0,"bar":2},{"foo":0,"bar":3},{"foo":0,"bar":4}]

但是对于有很多键的字典,有没有办法在不硬编码新字典的情况下做到这一点?

谢谢!

【问题讨论】:

  • foobar 是名称。它们不是字典。它们都是同一个字典对象的名称。
  • 当您执行a = b = dict() 时,您的两个变量都引用了内存中的同一个对象。如果你想复制一些东西,请使用标准库中的copy
  • python 中的相等运算符基本上是创建一个指向另一个项目的链接,而不是复制值
  • a=b=any_object 表示ab 引用同一个对象any_object
  • 这能回答你的问题吗? Does python copy objects on assignment?

标签: python python-3.x dictionary theory


【解决方案1】:

那是因为当你将可变变量(比如包含 dict、list 等的变量)分配给另一个变量(或者你将它传递给函数)时,它是通过引用传递,而不是通过值传递。这意味着变量存储对象的引用,而不是实际值。另一方面,像 int、str、float 等常量是按值传递的。这意味着制作了它们的副本。如果你想通过值传递一个可变项,你需要像这样使用copy.deepcopy 复制它:

import copy
my_dict = {"a": 1, "b": 2}
my_copy_dict = copy.deepcopy(my_dict)

现在,当您将 my_dict 更改为 my_copy_dict 时,它们将不会同步。

【讨论】:

  • 您的“常量”仍然通过引用传递(和分配)。主要区别在于它们不是可变的。
猜你喜欢
  • 2015-05-20
  • 2014-03-26
  • 2018-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多