If I execute this code:
fs = []
for i in [1, 2, 3, 4]:
def f():
print(i)
fs += [f]
for f in fs:
f()
It prints:
4
4
4
4
I don't understand why. And how to make it print this:
1
2
3
4
If I execute this code:
fs = []
for i in [1, 2, 3, 4]:
def f():
print(i)
fs += [f]
for f in fs:
f()
It prints:
4
4
4
4
I don't understand why. And how to make it print this:
1
2
3
4
to follow up @AirSquid answer, if you execute the following code, you will see the id(i) indicating the same address.
fs = []
for i in [1, 2, 3, 4]:
def f():
print(id(i))
print(i)
fs += [f]
for f in fs:
f()
print(f)
when your for-loop over i
completes, the last value of i
that was assigned is 4. So that is the value of i
when you loop over fs
Going back to your fs
variable... You are just appending the originally empty list with 4 references to the (oddly placed) function, so it is just a list that has 4 things in it. What they are is immaterial in this case.
So, in your last for-loop, it iterates 4 times (the length of fs
) and each time it calls f() which internally assumes that i
is a global variable and it prints the last value.
If you want to make it print 1, 2, 3, 4
, delete everything and write a better structured chunk of code and a function that takes a parameter i
that you pass in or such.
hence its a pointer passed to function it need to be evaluated before being appended to list
my functional approach to this would be following:
fs = []
loop = [1, 2, 3, 4]
for i in [1, 2, 3, 4]:
def f():
string = f'print({i})'
def f2():
eval(string)
return f2
fs += [f()]
for _f in fs:
_f()
output:
1
2
3
4
UPDATE:
you could also do this, makes more sense to me:
creating tuples of function and i instances then calling them with each other:
fs = []
for i in [1, 2, 3, 4]:
def f(j):
print(j)
fs += [(f, i)]
for i in fs:
i[0](i[1])