Python的dict.pop是原子的吗?

zig*_*igg 12 python dictionary

认为以dict.pop原子方式运行似乎是合理的,因为KeyError如果指定的键丢失并且没有提供默认值则会引发,如下所示:

d.pop(k)
Run Code Online (Sandbox Code Playgroud)

但是,文档似乎并没有专门针对这一点,至少在专门记录的部分没有dict.pop.

当我正在审查使用这种模式的我的答案时,我想到这个问题:

if k in d: del d[k]
Run Code Online (Sandbox Code Playgroud)

那时候,我并没有想到一把钥匙可能存在的潜在条件if,而不是当时del.如果dict.pop确实提供了原子替代方案,那么我应该在我的答案中注意到.

Mar*_*ers 26

对于默认类型,dict.pop()是C函数调用,这意味着它是通过一个字节码评估执行的.这使得该调用原子化.

Python线程仅在字节码评估循环允许时才切换,因此在字节码边界处.一些Python C函数会回调到Python代码(想想__dunder__特殊方法钩子),但该dict.pop()方法不会,至少不是默认dict类型.


ren*_*kiy 5

实际上 dict.pop() 不是原子的。例如,如果您使用对象作为字典的键,Python 必须调用对象的 __hash__() 实现。但是你可以使用 dict.popitem() 来代替,它是真正的原子性的。

  • 您的答案从根本上与最重要和接受的答案相矛盾。你还相信你的想法是正确的吗?如果是这样,为什么?否则,您能否添加免责声明或其他内容,以免像我这样的人感到困惑? (2认同)
  • 我的意思是用作字典键的用户定义类的实例。 (2认同)
  • 当执行诸如“d.pop(key, None)”之类的操作时,只有一个线程获取该值,其他线程获取“None”,对吧?即使两个线程“hash(key)”只有一个线程会赢得将其从字典中删除的竞赛。就像“d.pop(generate_key(), None)”可能不是原子的,因为“generate_key()”不是原子的,但从 dict 中删除仍然是原子的。 (2认同)
  • @YatharthAgarwal 可接受答案的标准已经改变。在 2019 年,我认为我们会说 martijn-pieters 没有回答这个问题,因为这个问题没有提到默认类型。它也依赖于实现。永远不要被名声吓倒。 (2认同)