当使用中间变量时,Python字典会发生变化。

13 浏览
0 Comments

当使用中间变量时,Python字典会发生变化。

我正在为一个函数提供一个字符串,该函数逐个字符地读取字符串。根据正在处理的字符,从字典中调用一个JSON模板,稍微编辑并保存到最终的字典中,然后将解析为JSON并保存。

问题是这个模板字典应该保持不变,但实际上并没有。不知何故,我写入中间变量的值被保存到原始模板字典中,从而破坏了我试图保存的后续数据。

我是否遗漏了某些字典的基本概念?这是我第一次在如此广泛的范围内使用字典,所以我甚至不会感到惊讶。

模板字典:

self.map_legend = {"#": {"Id": 100, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "墙", "PlayerNumber": 0},

"—": {"Id": 200, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "盾牌", "PlayerNumber": 0},

"x": {"Id": 300, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "外星人", "PlayerNumber": 0},

"|": {"Id": 400, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "外星人子弹", "PlayerNumber": 0},

"!": {"Id": 500, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "导弹", "PlayerNumber": 0},

"i": {"Id": 500, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "导弹", "PlayerNumber": 1},

"M": {"Id": 600, "Alive": False, "X": 0, "Y": 0, "Width": 3, "Height": 1, "Type": "导弹控制器", "PlayerNumber": 0},

"X": {"Id": 700, "Alive": False, "X": 0, "Y": 0, "Width": 3, "Height": 1, "Type": "外星人工厂", "PlayerNumber": 0},

"A": {"Id": 800, "Alive": False, "X": 0, "Y": 0, "Width": 3, "Height": 1, "Type": "飞船", "PlayerNumber": 0},

"V": {"Id": 800, "Alive": False, "X": 0, "Y": 0, "Width": 3, "Height": 1, "Type": "飞船", "PlayerNumber": 1},

" ": {"Id": 900, "Alive": False, "X": 0, "Y": 0, "Width": 1, "Height": 1, "Type": "空格", "PlayerNumber": 0}}

问题代码:

对于self.initial_game_map中的每个字符:

如果字符不是"\n":

从self.map_legend中获取元素

self.id_counters[char] += 1

element["Id"] = self.id_counters[char] + element["Id"]

element["Alive"] = True

element["X"] = char_counter % self.state_json["Map"]["Height"]

element["Y"] = char_counter / self.state_json["Map"]["Height"]

打印self.map_legend[char]

打印element

将element添加到row中

element = {}

char_counter += 1

否则:

将row添加到self.state_json["Map"]["Rows"]中

row = []

一些输出:

V

{'Width': 3, 'PlayerNumber': 1, 'Y': 1, 'X': 2, 'Type': '飞船', 'Id': 801, 'Alive': True, 'Height': 1}

{'Width': 3, 'PlayerNumber': 1, 'Y': 1, 'X': 2, 'Type': '飞船', 'Id': 801, 'Alive': True, 'Height': 1}

#

{'Width': 1, 'PlayerNumber': 0, 'Y': 0, 'X': 18, 'Type': '墙', 'Id': 103, 'Alive': True, 'Height': 1}

{'Width': 1, 'PlayerNumber': 0, 'Y': 0, 'X': 18, 'Type': '墙', 'Id': 103, 'Alive': True, 'Height': 1}

可以看到element变量的行为是预期的,但是可以看到self.map_legend在element更改后以某种原因承担了element的值,这不是我想要的。发生了什么?

0
0 Comments

在Python中,当使用中间变量时,字典可能会发生变化。出现这种情况的原因是elementself.map_legend[char]指向同一个字典,因此如果更新element,将会更新字典self.map_legend[char]的值。如果你想要一个副本,可以使用element = self.map_legend[char].copy()。关于这个问题,你可以在Python文档中找到相关参考:https://docs.python.org/2/library/copy.html。由于字典是浅拷贝的,所以不需要使用.deepcopy()

谢谢,这个方法有效。我怀疑可能是这样的情况,但不确定。在我使用Python编程的17年中,有时候仍然会被这个问题困扰。顺便说一下,在使用列表时也应该注意相同的问题。在这种情况下,可以使用newlist = oldlist[:](只要列表是浅拷贝的)。

谢谢你的提示 🙂 什么情况下列表/字典是“深拷贝”的?

(可能有官方定义),但一个经验法则是:如果字典或列表中的任何值本身需要进行(浅)拷贝(即该值是列表、字典或类的实例),那么它就是深拷贝的。

0
0 Comments

当在Python中使用中间变量时,字典会发生改变的原因是因为字典在Python中是可变对象。当我们将一个字典赋值给一个中间变量时,实际上是将该字典的引用传递给了中间变量。这意味着当我们修改中间变量时,原始字典也会发生相应的改变。

为了解决这个问题,我们可以使用深拷贝(deepcopy)来创建中间变量。深拷贝会创建一个与原始字典完全独立的副本,使我们能够对中间变量进行修改而不影响原始字典。

下面是使用深拷贝解决该问题的示例代码:

from copy import deepcopy
element = deepcopy(self.map_legend[char])

通过使用深拷贝,我们可以确保中间变量的修改不会影响原始字典。这在需要对字典进行多次操作时非常有用,尤其是在涉及到嵌套字典或复杂数据结构时。

0