我在这里读过这些帖子,它们准确地解释了我面临的问题,但没有一个解决方案是有效的:
Changing one list unexpectedly changes another, too
Changing One dict value changes all values
我有一个特定形状的2D数组,我需要用它初始化字典中的条目。我是这样做的:
empty = []
for x in range(2):
empty.append([])
for y in range(2):
empty[x].append(False)
status = {k:[] for k in ["a", "b", "c"]}
status["a"] = list(empty)
status["b"] = list(empty)
status["c"] = list(empty)
print(status)
status["a"][0][0] = True
print(status)
(例如,简化列表的形状)
这张照片是:
{'a': [[False, False], [False, False]], 'b': [[False, False], [False, False]], 'c': [[False, False], [False, False]]}
{'a': [[True, False], [False, False]], 'b': [[True, False], [False, False]], 'c': [[True, False], [False, False]]}
如您所见,设置一个列表值会更改所有列表。我不希望这样,我希望它们是具有不同值的单独列表(在一个字典中)
起初,我认为我犯了老的newlist = oldlist
错误,将newlist设置为与oldlist相同的对象,但没有。正如您在我的代码中所看到的,我使用newlist = list(oldlist)
创建单独的列表。我也试过newlist = oldlist[:]
、newlist = oldlist.copy()
等等
我错过了什么
你和副本很接近,但实际上你需要一份深度副本
您可以看到
empty
列表的第一个元素在字典中的所有值之间共享:它们都共享相同的内存位置。空列表中的第二项也是如此,
id(empty[1]) == id(status['a'][1]) == ...
原因是您将
empty
列表分配给每个值。您可以对这个空的嵌套列表执行深度复制,或者使用列表理解为字典中的每个键生成新的列表。空列表创建的列表理解本身是在字典理解中完成的,以便为所有必需的键生成status
变量现在,您可以在不影响其他元素的情况下更改任何元素
正如我前面所说,
list(empty)
确实创建了一个新列表,但是这个新列表的内部列表只是对empty
中相同列表对象的引用您可以使用^{} ,但我认为在需要时构建新列表更简单。
deepcopy
函数跳过各种环,这些环是复制可以包含任何内容的任意深度嵌套对象所必需的。但是,当你有一个简单的从头开始构建的结构时,为什么还要费心去做这些事情呢使用列表理解,您的代码可以这样编写:
对最里面的列表执行
[False] * 2
是安全的:共享不可变对象(布尔、整数、字符串等)总是安全的。只有当您意外地共享一个可更改的对象,并且您更改了它的值而不是用新对象替换它时,问题才会出现为了避免重新编写列表comp,可以使用函数为您构建列表。例如
输出
相关问题 更多 >
编程相关推荐