2013-06-26 5 views
9

Разумно полагать, что dict.pop работает атомарно, так как он повышает KeyError если указанный ключ отсутствует, и не предоставляется по умолчанию, например, так:Является ли python dict.pop атомом?

d.pop(k) 

Однако, документация не представляется конкретно решить эту точку , по крайней мере, не в разделе, специально документирующем dict.pop.

Этот вопрос мне пришло в голову, когда я просматривал an answer of mine, который использовал этот шаблон:

if k in d: del d[k] 

В то время я не думал о потенциальном условии, что ключ может присутствовать во время if, но не на момент del. Если dict.pop действительно представляет собой атомную альтернативу, то я должен отметить это в своем ответе.

+2

Связанные: [Какие виды глобальных изменений мутаций являются потокобезопасными?] (Http://goo.gl/dHxwN) –

ответ

21

Для типа по умолчанию dict.pop() является вызовом функции C, а это значит, что оно выполнено с помощью одного оценки байт-кода. Это делает этот вызов атомарным.

Нити Python переключаются только тогда, когда цикл оценки байт-кода позволяет им, поэтому на границах байт-кода. Некоторые функции Python C переходят в код Python (думаю, __dunder__ специальные крючки метода), но метод dict.pop() не имеет, по крайней мере, не для типа dict по умолчанию.

+0

Отличное объяснение ... –

+0

Путь выше моего объяснения объяснения. Только один вопрос: кто-нибудь получил представление о ситуации в Jython? –

+0

См. [Документация по параллелизму Jython] (http://www.jython.org/jythonbook/en/1.0/Concurrency.html): * Jython реализует dict и устанавливается с помощью ConcurrentHashMap Java. Это означает, что вы можете просто использовать эти стандартные типы Python и по-прежнему получать высокопроизводительный параллелизм. (Они также являются атомарными, как в CPython, как мы опишем.) * –

2

Фактически dict.pop() не является атомарным. Например, если вы используете объект в качестве ключа dict, Python должен вызывать реализацию __hash __() объекта. Но вы можете использовать dict.popitem() вместо этого, который поистине атомный.

+1

Ваш ответ принципиально противоречит верхнему и принятому ответу. Вы все еще считаете, что ваша правда? Если да, то почему? Еще бы, не могли бы вы поставить отказ или так, чтобы такие люди, как я, не путались? –

+0

Не принципиально. @ martijn-pieters рассказал о стандартных типах (фактически базовых типах). Но, как правило, не стоит надеяться, что dict.pop() всегда атомарно. – renskiy

+0

Когда вы говорите _ «если вы используете объект в качестве ключа dict» _, что вы подразумеваете под объектом? Я думал * все * в Python было одним? –