Search code examples
pythonpython-3.xfunctionnested-function

How to capture a value for later in a nested function?


def make_functions():
    flist = []

    for i in [1, 2, 3]:
        def print_i():
            print(i)
        flist.append(print_i)

    return flist

functions = make_functions()
for f in functions:
    f()

The output of this code is:

3
3
3

Questions:

  1. Why does print_i only capture the final value of i?
  2. How can we modify this code to make it print 1, 2, 3?

One way to answer question #2 is as follows, but I'm wondering if there's a more elegant way that captures the value of i.

def make_functions():
    flist = []

    for i in [1, 2, 3]:
        def print_i(j):
            print(j)
        flist.append((print_i, i))

    return flist

functions = make_functions()
for f, i in functions:
    f(i)

Solution

  • Because scope of i in your case is of make_functions, you should make a separated scope for it, here I wrap it into a function

    def make_functions():
        flist = []
    
        for i in [1, 2, 3]:
            def print_i_factory(i):
                def print_i():
                    print(i)
    
                return print_i
    
            flist.append(print_i_factory(i))
    
        return flist
    
    functions = make_functions()
    for f in functions:
        f()