如果不存在,Python会在dict中更新密钥

Xia*_*Cui 53 python dictionary

如果key不在dict.keys()中,我想在dict中插入一个键值对.基本上我可以这样做:

if key not in d.keys():
    d[key] = value
Run Code Online (Sandbox Code Playgroud)

但有更好的方法吗?或者这个问题的pythonic解决方案是什么?

Mar*_*ers 73

您的语法无效,也不需要调用d.keys().

if key not in d:
    d[key] = value
Run Code Online (Sandbox Code Playgroud)

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

您可以再次更新dict.get(),如果密钥已存在,则会返回现有值:

d[key] = d.get(key, value)
Run Code Online (Sandbox Code Playgroud)

但我强烈建议不要这样做; 这是代码打高尔夫球,妨碍维护和可读性.

  • @ed22是的,因为它由多个字节码指令组成,线程可以在这些指令之间切换。 (3认同)
  • 如果我有多个线程使用该代码,我是否需要同步它? (2认同)

mha*_*wke 35

用途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'}
Run Code Online (Sandbox Code Playgroud)

  • @MartijnPieters 我想说你错了。对于“期望值存在的表达式”,但您不想更新字典,您只需使用具有默认值的“get”即可。`setdefault` 的全部要点是它确实执行更新 - 然后它也自然地为相关元素提供一个左值,但是否立即使用它取决于您。 (11认同)
  • @MartijnPieters:为什么这么重要?名称`setdefault()`清楚地描述了正在发生的事情 - 它也返回一个不重要的值,并且有点古怪的IMO.您能否提供一个快速解释或链接到一个,为什么这是不可取的? (7认同)
  • @MartijnPieters:谢谢你的解释.阅读完文档字符串后,`setdefault()`似乎确实适合你所说的内容.使用`defaultdict(list)`会产生比你的例子更可读的代码......所以除非必须使用标准字典,否则它可能没用.总的来说,`如果不在d中的键更清晰. (6认同)
  • 你可以在一个期望值存在的表达式中使用它,比如在分组循环中:`for itej in iterable:d.setdefault(key_for_obj(obj),[]).append(obj)`.返回的值没有什么古怪,*这是方法的全部要点*. (5认同)
  • `dict.setdefault()`应该只在尝试访问该值时使用. (4认同)
  • 此外,它掩盖了您要执行的操作,即仅在键不存在时才设置键。可读性很重要,只需使用 `if key not in d:` 测试。 (2认同)

Rot*_*eti 34

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

new_dict = old_dict | { key: val }
Run Code Online (Sandbox Code Playgroud)

例如:

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

print(new_dict} # {'a': 1, 'b': 42}
Run Code Online (Sandbox Code Playgroud)

注意:这会使用更新的值创建一个新字典。

  • 虽然这很有趣,但我认为它并不比公认的答案更具可读性 (9认同)
  • 问题是询问如何“更新字典中的键 *如果它不存在*”,以便字典所需的输出保持相同 `{ 'a': 1, 'b': 2 }` 因为old_dict 中已有“b”。所以你必须把另一个字典放在前面 `{ key: val } | 旧字典`。 (9认同)
  • 对我来说,很高兴知道现在有一种方法可以合并两个字典 (2认同)
  • @JoeFerndz 右侧的字典优先,不会忽略该值。我更新了示例以使其更加清晰。 (2认同)

小智 15

您还可以仅在一行代码中使用此解决方案:

dict[dict_key] = dict.get(dict_key,value)
Run Code Online (Sandbox Code Playgroud)

的第二个参数dict.get是您要分配给该键的值,以防该键不存在。由于它在分配给 之前进行评估dict[dict_key] = ,因此我们可以确定当我们尝试访问它时它们的键将存在。


小智 8

使用以下内容,您可以插入多个值并具有默认值,但您正在创建一个新字典。

d = {**{ key: value }, **default_values}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 太感谢了。但似乎应该是 `{**default_values, **{ key: value }}` (3认同)