Issues to be aware of with Python closures

definition

     Closures in python are defined expressively as: if in an inner function, a reference is made to a variable in the outer scope (but not in the global scope), then the inner function is considered to be a closure, That is to say, the case where the inner function references the variables of the outer function and then returns the inner function is called a closure.
  Closures are characterized in that the returned function also references the local variables of the outer function. So, to use closures correctly, make sure that the referenced local variables cannot be changed after the function returns.

example

#Hope to return six functions, calculate 3*0, 3*1, 3*2, 3*3, 3*4, 3*5   
def operator():  
     return [ lambda m: n * m for n in range( 6 )]  
  
print [o(3) for o in operator()]  

The above code is equivalent to:

#Hope to return six functions to calculate 3*0, 3*1, 3*2, 3*3, 3*4, 3*5   
def operator():  
    fs = []  
    for n in range(6):  
        def func(m):  
            return m * n  
        fs.append(func)  
    return fs  
  
print [o(3) for o in operator()]  

    The local variable n of the outer function is used in the inner function func(), but n is changed. We originally expected the output result to be [0, 3, 6, 9, 12, 15], but in fact the output The result is [15, 15, 15, 15, 15, 15].

        The reason is because n is changing. When operator() returns these six functions, the n referenced by these six functions has become 5. Since these six functions have not been called, m×n is not calculated. When called, n has become 5, so 6 15s are output.
        This result is mainly due to the late binding mechanism in Python, that is, the value of the variable in the closure is only queried when the inner function is called. So, in the code above, every time the function returned by operator() is called, the value of variable n is queried in a nearby scope (and by that time, the loop is over, so variable n is last assigned value is 5).
        So how to modify the code to make the result meet our expectations.

Improve

#Hope to return six functions, calculate 3*0, 3*1, 3*2, 3*3, 3*4, 3*5   
def operator():  
     return [ lambda m, n=n: n * m for n in range(6 )]  
   
print [o(3) for o in operator()]  

or:

#Hope to return six functions to calculate 3*0, 3*1, 3*2, 3*3, 3*4, 3*5   
def operator():  
    fs = []  
    for n in range(6):  
        def func(m, n=n):  
            return m * n  
        fs.append(func)  
    return fs  
  
print [o(3) for o in operator()]  

output:

[0, 3, 6, 9, 12, 15]  

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324940130&siteId=291194637