3
func = []

for value in range(5):
    func.append(lambda: print_index(value))


def print_index(index_to_print):
    print(index_to_print)


for a in func:
    a()

When I run the code above, the output is

4
4
4
4
4

Why is it not ?

0
1
2
3
4

What can I do to make it like the above.

I have tried importing copy and using copy.deepcopy(index). I didn't work probably since index is an integer.

Is lambda part of the reason it is not working.

Thank you for your help!

user2357112
  • 260,549
  • 28
  • 431
  • 505
staad
  • 796
  • 8
  • 20
  • Possible duplicate of [Local variables in Python nested functions](https://stackoverflow.com/questions/12423614/local-variables-in-python-nested-functions) – user2357112 Jul 16 '17 at 23:18

2 Answers2

3

Not quite sure what you are trying to achieve but the reason that it is printing all 4s is because Python uses dynamic name resolution of variables, that is the value of value when the functions are executed (not when it is declared) is used.

If you really need a function to print the value then you need to create a closure, which means creating the function inside another function, e.g.:

def make_closure(v):
    return lambda: print_index(v)

func = [] 
for value in range(5):
    func.append(make_closure(value))

Now this outputs:

In []:
for a in func:
    a()

Out[]:
0
1
2
3
4
AChampion
  • 29,683
  • 4
  • 59
  • 75
1

As @AChampion said, Python calculates the value of value when it needs to and not while executing the loop.

However for me it seemed easier to do the following fix.

func = []

for value in range(5):
    func.append(lambda v = value: print_index(v))


def print_index(index_to_print):
    print(index_to_print)


for a in func:
    a()

This is setting the default argument in the function which gets calculated during the loop execution. The code above is the same as saying :

func = []

for value in range(5):
    def anonymous_function(v=value):
        print_index(v)

    func.append(anonymous_function)


def print_index(index_to_print):
    print(index_to_print)


for a in func:
    a()
Alex Meiburg
  • 655
  • 5
  • 20
staad
  • 796
  • 8
  • 20