Code
Initially, I have some instances of classes stored in a dictionary, each with some initialized attribute.
class A:
def __init__(self):
self.foo = 'bar'
my_dict = {}
for i in range(3):
my_dict[i] = A()
Now, I call a function on a dictionary value, my_dict[1], say, wanting to change the .foo attributes of all values in the dictionary, except that of my_dict[1], which I would like to change differently.
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()))
However, the third line under outer(v) ends up changing my_dict[2].foo instead.
Problem
Consider the three lines in the function outer(v), and the output from the print(...).
- Without first two lines, gives
[(0, 'bar'), (1, 'sand'), (2, 'bar')]as expected. - Without third line, gives
[(0, 'nada'), (1, 'nada'), (2, 'nada')]as expected. - However, with all three lines, gives
[(0, 'nada'), (1, 'nada'), (2, 'sand')].
This suggests the variable v has been 'stuck' at index 2, following exit from for-loop. Why does Python do this?
Background
This problem caused a huge hold-up in a larger program I was making. This is my first attempt at asking a question on Stack Overflow by making a minimal, reproducible example. Any advice on how to make the question clearer or better is very much appreciated. Thank you.
vin your for-loop, i.e.for k,v in my_dict.items():. Now,vin the last line of your function will refer to whatevervis on the last iteration of your for-loop. I'm not sure what you are asking. Why does Python do this? You did this. But assigning tov, essentially, ignoring whatever value you passed in to the parameterv. I'm confused, because you already seem to understand that when you say shadowed.for k in my_dict:when not using the value inside the loop, so I guess the error you get being a side-effect of that is just karma. ;)