如果不存在,Python将更新dict中的键


Answers:


152

您无需致电d.keys(),因此

if key not in d:
    d[key] = value

足够的。没有更清晰,更易读的方法。

您可以使用再次更新dict.get(),如果键已经存在,它将返回一个现有值:

d[key] = d.get(key, value)

但我强烈建议您反对;这是代码打高尔夫球,妨碍了维护和可读性。


如果我有多个使用该代码的线程,是否需要对此进行同步?
ed22 '20年

1
@ ed22是的,因为它由多个字节码指令组成,可以在线程之间进行切换。
马丁·彼得斯

84

用途dict.setdefault()

>>> d = {1: 'one'}
>>> d.setdefault(1, '1')
'one'
>>> d    # d has not changed because the key already existed
{1: 'one'}
>>> d.setdefault(2, 'two')
'two'
>>> d
{1: 'one', 2: 'two'}

6
dict.setdefault()也应该仅在尝试访问该值时才使用。
马丁·彼得斯

14
@MartijnPieters:为什么这么重要?这个名称setdefault()清楚地描述了正在发生的事情-它也返回一个值并不重要,而且IMO有点古怪。您能否提供一个快速的解释或链接,以了解为什么不希望这样做?
mhawke

6
您可以在期望值存在的表达式中使用它,例如在分组循环中:for obj in iterable: d.setdefault(key_for_obj(obj), []).append(obj)。返回的值没有任何古怪之处,这就是方法的重点
马丁·彼得斯

2
另外,它会掩盖您要尝试执行的操作,即仅在尚不存在的情况下设置密钥。可读性很重要,只需使用if key not in d:测试即可。
马丁·彼得斯

7
@MartijnPieters:感谢您的解释。阅读了文档字符串,setdefault()似乎确实适合您所说的内容。使用adefaultdict(list)比代码示例更具可读性...因此,除非有人必须​​使用标准字典,否则可能没有用。总体而言,if key not in d更为清晰。
mhawke

25

Python 3.9开始,您可以使用merge运算 |符合并两个字典。右侧的dict优先:

new_dict = old_dict | { key: val }

例如:

new_dict = { 'a': 1, 'b': 2 } | { 'b': 42 }

print(new_dict} # {'a': 1, 'b': 42}

注意:这将创建具有更新值的新字典。


6
尽管这很有趣,但我认为它不比公认的答案更具可读性
Justin Furuness

2
对我来说,很高兴知道现在有一种方法可以合并两个字典
Austin A

这种合并存在挑战。如果键相同,则合并将忽略该值。如果这是目的,那么它会起作用。
Joe Ferndz

1
@JoeFerndz右边的dict优先,不会忽略该值。我更新了示例以使其更加清楚。
Rotareti

6

使用以下代码,您可以插入多个值,也可以使用默认值,但是您正在创建一个新字典。

d = {**{ key: value }, **default_values}

我已经用投票率最高的答案对其进行了测试,平均而言,这样做的速度更快,如下面的示例所示。

速度测试将基于for循环的方法与带有unpack运算符的dict理解进行比较 速度测试将基于for循环的方法与带有unpack运算符方法的dict理解进行比较。

如果d = default_vals.copy()在第一种情况下没有复制(),则一旦我们达到10**5或更大的数量级,投票最多的答案就会更快。两种方法的内存占用相同。


1
那为什么要首先提出建议
jonathan

1
该解决方案对我而言似乎完全有效。它还允许在一个声明中更新多个值。
Rotareti

非常感谢。但似乎应该是{**default_values, **{ key: value }}
osexp2003年

0

根据以上答案,setdefault()方法为我工作。

old_attr_name = mydict.setdefault(key, attr_name)
if attr_name != old_attr_name:
    raise RuntimeError(f"Key '{key}' duplication: "
                       f"'{old_attr_name}' and '{attr_name}'.")

虽然此解决方案不是通用的。在这种情况下才适合我。确切的解决方案是检查第key一个(如已经建议的),但是setdefault()我们避免在字典上进行额外的查找,即虽然很小,但仍然可以提高性能。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.