Я пишу программу, в которой мне нужно итерационно просматривать множество длинных словарей, поэтому я подумал, что могу удалить из них ненужные значения, чтобы сэкономить время выполнения. Вот минимальный рабочий пример с отсутствующим контекстом:

years = {0: 2019, 1: 2020, 2: 2021}


def iterate_years():
    for i in years:
        temp_years = years
        print("years:", years)
        print("temp_years:", temp_years)
        temp_years.pop(i)
        minimum = min(temp_years)
        maximum = max(temp_years)
        print("temp_years:", years)
        print("years:", years)


iterate_years()

Когда я запускаю эту функцию, она возвращает ошибку времени выполнения, поскольку размер словаря изменился во время итерации. Как видно из примера, строка temp_years.pop(i), похоже, выводит пару ключ-значение i в temp_years, как указано, но также и в years.
Почему так происходит? Я не очень опытен, но years никогда не присваивается temp_years после pop(), поэтому значения для years должны оставаться такими, как они были указаны в первой строке.

PaddyFH

Ответы (2)

Проблема в том, что temp_years и years указывают на один и тот же объект в памяти (ссылка), вы можете проверить это, сравнив id обеих переменных:

>>> id(temp_years) == id(years)
>>> True

Если вам нужна копия, вы должны создать новый dict с temp_years = years.copy(). Но если в словаре есть вложенные объекты, вам придется сделать глубокую копию, потому что dict.copy() делает только глубокую копию.

>>> import copy
>>> temp_years = copy.deepcopy(years)
>>> id(temp_years)
140641196228824
>>> id(years)
140641197662072

Вы должны создать копию при создании диктанта temp_years, иначе он будет функционировать как указатель на исходный объект (years). Поэтому изменения, которые вы вносите в temp_years, также изменяют years. Поэтому все, что вам нужно, это изменить эту строку присваивания:

temp_years = years.copy()

Вы также можете сделать его deepcopy, если это вложенный dict (иначе вы получите только ключи верхнего уровня):

import copy
temp_years = copy.deepcopy(years)

Посмотрите этот ответ для получения более подробной информации: Как скопировать словарь и редактировать только копию

2022 WebDevInsider