Код
Изначально у меня есть несколько экземпляров классов, хранящихся в словаре, каждый с некоторым инициализированным атрибутом.
class A:
def __init__(self):
self.foo = 'bar'
my_dict = {}
for i in range(3):
my_dict[i] = A()
Теперь я вызываю функцию для значения словаря, скажем, my_dict[1]
, желая изменить атрибуты .foo
всех значений в словаре, кроме атрибута my_dict[1]
, который я хотел бы изменить по-другому.
def outer(v):
for k,v in my_dict.items():
my_dict[k].foo = 'nada'
v.foo = 'sand'
my_entry = my_dict[1]
outer(my_entry)
print(list((k,v.foo) for (k,v) in my_dict.items()))
Однако третья строка под outer(v)
вместо этого меняет my_dict[2].foo
.
Проблема
Рассмотрим три строки в функции outer(v)
и вывод функции print(...)
.
- Без первых двух строк дает
[(0, 'bar'), (1, 'sand'), (2, 'bar')]
, как и ожидалось. - Без третьей строки дает
[(0, 'nada'), (1, 'nada'), (2, 'nada')]
, как и ожидалось. - Однако со всеми тремя строками дает
[(0, 'nada'), (1, 'nada'), (2, 'sand')]
.
Это говорит о том, что переменная v «застряла» на индексе 2 после выхода из цикла for. Почему Python делает это?
Фон
Эта проблема вызвала огромную задержку в большой программе, которую я делал. Это моя первая попытка задать вопрос о переполнении стека на минимальном воспроизводимом примере. Любые советы о том, как сделать вопрос яснее или лучше, очень ценятся. Спасибо.
v
в цикле for, то естьfor k,v in my_dict.items():
. Теперьv
в последней строке вашей функции будет ссылаться на то, чтоv
находится на последней итерации вашего цикла for. Я не уверен, что вы спрашиваете. Почему Python делает это? Вы сделали это. Но назначениеv
, по сути, игнорирует любое значение, которое вы передали параметруv
. Я в замешательстве, потому что вы, кажется, уже понимаете это, когда говорите «затененный». - person juanpa.arrivillaga   schedule 12.12.2019for k in my_dict:
, когда не используете значение внутри цикла, поэтому я думаю, что ошибка, которую вы получаете, является побочным эффектом, это просто карма. ;) - person Jeronimo   schedule 12.12.2019