Analysis of Variable Scope of Closure in Python Programming

  • 2021-12-11 08:03:17
  • OfStack

Variables in directory closure closures

Closure

When we use the return function, because we need to return another function in one function, we need to redefine one function in this function. In this way, our function nesting problem is caused. The outer function is an outer function relative to the inner function (outer function), and the inner function is called an inner function (inner function).


def outerFunction(): # External function 
    def innerFunction(): # Inner function 
        x = 1
        return x
    return innerFunction # The return value is 1 Functions 
a = outerFunction()
print(a)

Here, when we print the value of a, we are actually printing the address of our return function:

< function outerFunction. < locals > .innerFunction at 0x0000019C278C0E50 >

1 In general, when we use a function as a return value, we use a variable in our outer function in the inner function, which leads to an interesting thing. The inner function is returned to the other external caller, and our variables are defined in our outer function. At this point, how will the scope of our variables change?

Test:


def outerFunction(x): # External function 
    y = 10
    def innerFunction(): # Inner function 
        return x + y
    return innerFunction # The return value is 1 Functions 
a = outerFunction(10)
print(a())

Print:

20

It can be seen here that when we assign a value to a, we pass a value of 10 to the outer function at the same time, and then we print out a () directly. At this time, our a returns 20, indicating that our inner function will retain the value of this variable after our variables and parameters enter the inner function.

Here, we call this "closure (Closure)", and I try to return this inner function several times to see if their address is 1:


def outerFunction(x): # External function 
    y = 10
    def innerFunction(): # Inner function 
        return x + y
    return innerFunction # The return value is 1 Functions 
a = outerFunction(10)
b = outerFunction(20)
c = outerFunction(30)
print(a())
print(b())
print(c())
print(a)
print(b)
print(c)

Print:

20
30
40
< function outerFunction. < locals > .innerFunction at 0x0000020C480C0DC0 >
< function outerFunction. < locals > .innerFunction at 0x0000020C480C0D30 >
< function outerFunction. < locals > .innerFunction at 0x0000020C480CD280 >

Here we can see that the address of each innerFunction is different. When we call the return function many times, every time we call it, our return function will create a new function for our variable.

So, if we call our inner function many times inside the outer function, what is the scope of the variables of our outer function?

Let's test 1:


def outerFunction(x): # External function 
    L=[] # Definition 1 A List 
    y = 10
    for i in range(1, 4):
        def innerFunction(): # Inner function 
            return (x + y) * i # Variables that use our external functions 
        print(innerFunction()) # Print the value returned by the function within 
        #print(innerFunction)
        L.append(innerFunction) # Add inner functions to our List Medium 
    return L # Returns this List
a = outerFunction(10)
print(a[0])
print(a[1])
print(a[2])
print(a[0]())
print(a[1]())
print(a[2]())

Look at the print:

20
40
60
< function outerFunction. < locals > .innerFunction at 0x00000274AD6B0E50 >
< function outerFunction. < locals > .innerFunction at 0x00000274AD6BD040 >
< function outerFunction. < locals > .innerFunction at 0x00000274AD6BD3A0 >
60
60
60

Here we can see an interesting phenomenon:

When we call our inner function several times within our function and print out its return value, we can see that the value is normal (increasing in turn). And if we pass this inner function to our List, when we call it outside the function, the return values of our functions all become 60, that is, they only get the final values of the variables in our outer function. This is the unique phenomenon of our closure.

Variables in closures

In general, when a function ends, the local variables inside our function will be released together with the function 1 in memory.

However, when our function contains closures, that is, when the return value of this function is a reference to a function. At this point, when the function ends, because the local variable inside it needs to be released, it will pass the value of this variable to the inside of the function it wants to return. Because of this, when we call our return function externally, we will see that all the variables it uses are the final value of this variable within the function, because this variable is passed to our return function at the end of this external function. At this time, the variable in our function can only have one value.

However, we can use another method to avoid this situation:


def outerFunction(x): # External function 
    L=[] # Definition 1 A List 
    y = 10
    def innerFunction(i): # Inner function 
        def f():
            return (x + y) * i # Variables that use our external functions 
        return f
    for i in range(1, 4):
        print(innerFunction(i)()) # Print the return value of an inner function in an inner function 
        L.append(innerFunction(i)) # Add inner functions to our List Medium 
    return L # Returns this List
a = outerFunction(10)
print(a[0])
print(a[1])
print(a[2])
print(a[0]())
print(a[1]())
print(a[2]())

Print as follows:

20
40
60
< function outerFunction. < locals > .innerFunction. < locals > .f at 0x00000155B0F80040 >
< function outerFunction. < locals > .innerFunction. < locals > .f at 0x00000155B0F803A0 >
< function outerFunction. < locals > .innerFunction. < locals > .f at 0x00000155B0F80430 >
20
40
60

Here we can see that when we call externally, the return value of the function is the same as that of the internal call. Then we analyze the execution process of this function under 1 and the scope of variables in the function.

First of all, we add a layer of inner function f () to our inner function, and in this inner function, we use the parameters of the outer inner function innerFunction as the return value. Then, inside the for loop, we add the return value of our innerFunction function to our List.

We should have found it here. Within the for loop, When we add the return value f from innerFunction to our List, Because innerFunction is relative to the function f (), f () belongs to the inner function of innerFunction, so when we return f (), the value used inside f () is its final value, and at this time, our innerFunction function is still inside the for loop, so every time we call the return value of our innerFunction inside the loop, the value passed to our f () function is our final value.

At this point, even if we call the f () function externally, it returns the same value as when we call it internally.

The above is the Python programming in the closure of variable scope problem resolution details, more about the Python closure of variable scope information please pay attention to other related articles on this site!


Related articles: