poros
2/22/2016 - 2:16 AM

Python scoping quirks in closures applied to loops

Python scoping quirks in closures applied to loops

# python closures close over variables, not values
funcs = []
for i in range(4):  # `i` is actually created at the top of the enclosing function, only once
    # `i` has a new value assigned to it here
    def f():
        # Each incarnation of this function closes over the SAME VARIABLE, `i`
        print i
    funcs.append(f)

for f in funcs:
    f()
    
# prints 4 times 3


# SOLUTION 1
# factory function, because python scopes over functions
def make_f(i):
    def f():
        print i
    return f

funcs = []
for i in range(4):
    funcs.append(make_f(i))


# SOLUTION 2
# default values, because they are bound by value to the function
# just once the function is defined
# It is the same problem of the mutable argument f(a={}) or f(a=[]) which is going to be always the same
funcs = []
for i in range(4):
    def f(i=i):
        print i
    funcs.append(f)