Удаление элемента из во время прохода через него, как правило, приводит к RuntimeError: dictionary changed size during iteration
исключения:Почему изменение dict во время итерации не всегда вызывает исключение?
d = {1: 2}
# exception raised
for k in d:
del d[k]
Чтобы быть более точным, то само удаление будет успешным. Однако, чтобы ввести следующий раунд итерации, интерпретатор должен вызвать next(it)
, где it
является итератором через словарь, полученный ранее. В этот момент next()
заметят, что размер словаря изменился и жалуются.
Пока все хорошо. Но что, если мы оба удалить и добавить элемент в словарь:
d = {1: 1}
# no exception raised
for k in d:
# order of next two lines doesn't matter
d[k*10] = k*10
del d[k]
Я почти уверен, что это не безопасно (Документы подразумевают ни вставки не стирают допускаются в течение итерации). Почему интерпретатор разрешает запуск этого кода без ошибок?
Мое единственное предположение, что слишком дорого проверять, какие итераторы являются недействительными всякий раз, когда вызывается метод вставки или удаления. Таким образом, dict
не пытается быть идеальным в том, чтобы поднимать это исключение. Вместо этого он просто отслеживает размер словаря внутри каждого итератора и проверяет, что он не изменился всякий раз, когда итератору на самом деле предлагается перейти к следующему элементу. Нет ли такого подхода, который позволил бы провести полную проверку с низкой стоимостью?
Вы ищете что-то, чтобы сделать ваш цикл более надежным или вы хотите обсудить детали реализации Python? –
Похоже, вы хотите, чтобы словарные клавиши неизменялись во время цикла. Я не думаю, что это выполнимо. – DyZ
@KlausD. Хм, я думаю, оба? Если есть способ, который может это сделать, я бы подумал об этом. Но для того, чтобы понять его затраты (время выполнения, сложность кода и т. Д.), Мне было бы важно знать, почему CPython не использует его. – max