我的例子是这样的
for my_key in my_dict.keys():
my_dict[my_key].mutate()
是否定义了上述代码的行为(假设my_dict
是字典而mutate
是一个改变其对象的方法)?我担心的是,改变字典中的值可能会使字典的键上的迭代器无效。
另一方面,keys
方法的Python documentation表示它返回一个列表。如果是这样,我应该(我认为)能够改变字典的值,并且只要我不改变,添加或删除任何键,仍然可以安全地访问字典的每个元素。这是对的吗?
答案 0 :(得分:6)
是的,这是安全的,至少在所有基于C的Python实现中都是如此。它也是安全的:
for my_key in my_dict: # NOTE: no .keys() here
my_dict[my_key].mutate()
也就是说,安全性并不依赖于实现密钥列表,并且通常更有效的是不要仅仅为了遍历密钥而调用.keys()
。
请注意,在迭代期间完全替换与现有密钥关联的值也很好:
for my_key in my_dict:
my_dict[my_key] = something_new()
文档可以更清楚地了解这一点;-) 不是在迭代期间删除或添加密钥可预测的安全性。你对这些价值观所做的事情并不重要。
答案 1 :(得分:1)
是。这不是特定于Python,字典,甚至是基于散列的数据结构。
字典的内部结构完全基于其键。如果更改键周围的键可以更改字典的结构,如果在直接在字典上迭代的过程中发生,则迭代行为将变为未定义。特别是如果您想在迭代期间添加或删除键,那么您将使用.keys()
来避免实际迭代字典以避免此问题。如果你改变一个键就会完全被破坏,因此不允许使用可变的内置类型作为字典键。
但字典并不关心价值观。它们对存储或结构没有任何影响。它们只是一个侧面细节,是实现的一个微不足道的部分。它特别不关心你是否改变了这些值 - 实际上它无法知道你这样做了。
这应该不足为奇。这是你迭代的关键。您可以按键存储内容,然后按键检索它们。您检查密钥是否为in
字典,如果不是,您可能会获得KeyError
。值只是位于键旁边的那些东西,因此可以在找到键时找到并返回它们。
类似地,您可以迭代列表并在执行此操作时更改或替换其值,但不要追加或删除任何内容,因为这会影响内部结构。列表的索引就像它的键。
但是,您无法触摸集合的值,因为在集合中,键和值扮演相同的角色。
答案 2 :(得分:0)
该文件还说:
字典的值可以是任何类型,但键必须是不可变的数据类型,如字符串,数字或元组。
所以,你根本不能改变它们。