Local scope, beyond the scope of the enclosing

前端 未结 1 1020
一个人的身影
一个人的身影 2020-12-06 15:58

Why lambda function to get the list of values ​​i = 4 .During the call lambda, enclosing scope does not exist. The function f has finished work and returned control (the var

相关标签:
1条回答
  • 2020-12-06 16:41

    Python uses closures to capture references to the original variable. The lambda objects retain a reference to the i name, through which the value can be accessed. This means that the i variable continues to live on after f completes.

    You can introspect this closure in the .__closure__ tuple on the lambda objects; functions have the same attribute:

    >>> L[0].__closure__
    (<cell at 0x1077f8b78: int object at 0x107465880>,)
    >>> L[0].__closure__[0]
    <cell at 0x1077f8b78: int object at 0x107465880>
    >>> L[0].__closure__[0].cell_contents
    4
    

    This is also why all lambdas in your list L refer to the value 4, and not to the numbers 0 through to 4. They all refer to the same closure:

    >>> L[0].__closure__[0] is L[1].__closure__[0]
    True
    

    The closure refers to the variable, not to the value of that variable at the time the closure was defined. At the end of the loop i was last set to 4, so when looking up i in the lambda closure 4 will be found, for all lambdas in your list.

    If you want your lambdas to refer to the value of i during the loop, capture it in a keyword argument:

    def f():
        L = []
        for i in range(5): 
            L.append(lambda x, i=i: i ** x) 
        return L
    

    Now i is a local variable to the lambda, not a closure.

    Alternatively, create an entirely new scope from which to draw the closure:

    def create_lambda(i):
        return lambda x: i ** x
    
    def f():
        return [create_lambda(i) for i in range(5)]
    

    Now create_lambda() is a new scope with it's own local i for the lambda closure to refer to. The lambdas then each have their own closures:

    >>> L[0].__closure__[0] is L[1].__closure__[0]
    False
    

    Closures refer to a variable in a specific namespace; each time you call a function a new local namespace is created, so each closure refers to i in create_lambda in a separate namespace from other calls to create_lambda.

    0 讨论(0)
提交回复
热议问题