Closure functions in python
A preliminary study of closure functions
This is how we usually define functions
def foo(): pass
In fact, in functional programming, functions can also be nested inside functions, such as the following
def foo(): print("hello world in foo") def bar(): print("hello world in bar")
At this point we call the foo function, what will the result look like?
hello world in foo
As shown above, only the first layer of the foo function is executed, and the bar function is not executed. Why is that?
In fact, no matter where the function is written, it just defines a function, and only when the function is called, the statements inside the function will be executed
In the above example, the bar function is defined inside the foo function, but it is not executed, so the bar function is not executed. In this case, the function defined inside a function has no effect? That's not true.
Take a look at the following example, which returns the bar function as a value to the foo function to see the execution
def foo(): print("hello world in foo") def bar(): print("hello world in bar") return bar f1=foo() print(f1)
At this point, since the bar function is returned to foo as a return value, the result of the foo function is returned
At this point, define a variable f1 to receive the result of the execution of the foo function, and then print f1
The result returned is as follows
hello world in foo <function foo.<locals>.bar at 0x0000000002941A60>
You can see that a print statement defined in the foo function is printed first, followed by the memory address of the bar function contained in the foo function
Since it is the memory address of a function, it is possible to execute the function with parentheses
def foo(): print("hello world in foo") def bar(): print("hello world in bar") return bar f1=foo() f1()
At this point, the result of this code execution is:
hello world in foo hello world in bar
Both print statements are printed.
In the above example, we first define a function foo, then we nested a function bar inside the function foo, and then return the function name of the function bar, which is how the closure function is defined.
In fact, the definition of a closure is a function nested inside a function
Take a look at the following code
def foo(): print("hello world in foo") name="python" def bar(): print(name) print("hello world in bar") return bar f1=foo() f1()
In the above example, a variable name is defined in the outer function, and the variable name is printed in the inner function
At this time, when executing the above code, when printing the name variable, it will first look up the name variable inside the bar function, but there is no name variable in the bar function.
At this time, according to python's LEGB law for finding variables, it will go to the outside layer of the bar function to continue to find the name variable, and at this time, it can find the name variable
So here we print the value of name defined in the foo function
Execute the above code and print the following result
hello world in foo python hello world in bar
The important thing to remember here is:
The inner function refers to the local variable of the outer function
Let's analyze the execution of the program in the above example:
At this time, the result of the execution of the foo function is defined to the variable f1, so f1 is equal to the memory address of the bar function, and then f1 is run with parentheses to indicate that the bar function is run. During the execution of the bar function, the bar function accesses the variables defined in the outer function foo. This is a typical closure function. What is the benefit of using a closure function? In the above example, the value of f1 is the memory address of the bar function, and running f1 in parentheses is running the bar function.
Since f1 is a global variable, this means that the f1 function can be run anywhere in the entire program, and then define a function, and call the f1 function inside this function.
def foo(): print("hello world in foo") name = "python" def bar(): print(name) print("hello world in bar") return bar f1 = foo() def func(): name = "aaaaa" f1() func()
Let's analyze the execution process of the program:
1. Run the func function, the program will first apply a space in memory to store the value of the name variable, and then run the f1 function, f1 is a variable defined in the global, so it must be able to find the memory address of the f1 function
2. When f1 runs with parentheses, it executes a closure function that internally references the name variable
3. The name variable has been defined outside the bar function, so when the f1 function, that is, the bar function, is called inside the func function, the variable it refers to is still the name variable defined inside the foo function, instead of the name variable defined inside the func function.
4. Because the f1 function already contains the value of the name function, even if the name variable is defined inside the func function, the result of the program execution is still the value of the name defined inside the foo function
Result of program execution
hello world in foo python hello world in bar
How do you verify that a function is a closure function
First, closure functions have a unique property: closure
In the example above, print the __closure__ attribute of f1
def foo(): name = "python" def bar(): print(name) print("hello world in bar") return bar f1 = foo() print(f1.__closure__)
Print results are as follows:
(<cell at 0x0000000001DF5708: str object at 0x0000000001E79688>,)
You can see that the print result of the __closure__ attribute is a tuple whose value is the outer scope of the f1 function
The value of the name variable can then be printed by calling the cell_contents method of the element of the tuple returned by __closure__
def foo(): name = "python" def bar(): print(name) print("hello world in bar") return bar f1 = foo() print(f1.__closure__[0].cell_contents)
Print results are as follows:
python
You can see that the program has printed out the value of the name variable
If __closure__ returns a tuple, then this tuple must contain multiple values, see the following example
Define multiple variables inside the foo function, and then print the values of several variables inside the bar function,
Then run the closure function, printing the closure function's __closure__ method
def foo(): print("hello world in foo") name1 = "python1" name2 = "python2" name3 = "python3" name4 = "python4" def bar(): print(name1) print(name2) print(name3) print(name4) print("hello world in bar") return bar f1 = foo() print(f1.__closure__)
Result of program execution
(<cell at 0x0000000002145708: str object at 0x00000000021C9260>, <cell at 0x0000000002145A08: str object at 0x00000000021C93B0>, <cell at 0x0000000002145768: str object at 0x000000000295BE30>, <cell at 0x0000000002145C18: str object at 0x0000000002963880>)
Since four variables are defined inside the foo function and referenced inside the bar function, printing the closure function's __closure__ method returns a tuple with four elements
You can now print the values of each of the four string objects in the returned tuple separately
def foo(): name1 = "python1" name2 = "python2" name3 = "python3" name4 = "python4" def bar(): print(name1) print(name2) print(name3) print(name4) print("hello world in bar") return bar f1 = foo() print(f1.__closure__[0].cell_contents) print(f1.__closure__[1].cell_contents) print(f1.__closure__[2].cell_contents) print(f1.__closure__[3].cell_contents)
Result of program execution
python1 python2 python3 python4
So now there is one last question left, that is, must the inner function of the closure function return?
Consider the following example
def foo(): name = "python1" def bar(): print(name) print(bar.__closure__) foo()
A nested function is defined, and instead of returning the inner function of the nested function, the inner function's __closure__ method is printed and the outer function is called directly.
Result of program execution
(<cell at 0x0000000002155708: str object at 0x00000000021D9688>,)
Still prints out the variable object referenced by the inner function
This means that the inner function of the closure function must also return
Can an inner function of a closure function call a global variable?
Change the variable defined inside the outer function to a global variable, and then reference the variable in the inner function
name = "python1" def foo(): def bar(): print(name) print(bar.__closure__) f=foo() print(f)
Result of program execution
None
None
As you can see, the result of the execution of the program is two NOnes, and the __closure__ function of the inner function of the nested function has the value None
This means that the global variable called by the inner nested function bar of the foo function did not succeed, so the above example is not a closure function
Some summary of closure functions:
A closure is defined as:
A function defined inside a function is called an inner function. An inner function calls a local variable of an outer function. Local variables can still be used even if the inner function returns. Usually the inner function of a closure function is returned to the outer function
What closure functions do
1. Closure functions have their own function scope
Enclose enclose a normal function that looks outward layer by layer, conforming to the LEGB(Local-> >Global->Built in) law,
But for a closure function, finding a variable will only look for the layer outside the inner function, because the closure function itself has a layer of scope, which is the meaning of the word "closure"
2. Delayed computing (also known as lazy computing)
Take a look at the following example
def func(): name="python" def bar(): print(name) return bar f=func() print(f.__closure)
In the example above, the return result of executing foo() is a function that contains its own state, which is not actually executed.
In the future, when you want to execute this function with its own state, you can execute it by parenthesis the variable assigned by the func() return result.
3. To keep a function in a state, you can use closures
Example:
name="python" def func(): print("I like %s" % name) func()
The result of the above code execution will print a line :"I like python"
However, we know that the printing result of the func function is very likely to be different in different places
So if I want to call func anywhere and the result is "I like python",
You can use closures.
def func1(): name="python" def func(): print("I like %s" % name) return func func=func1() func()
As shown in the figure above, a second layer of function, func1, is included outside the func function, the func1 function is executed, and the result of the func1 function is assigned to the func variable
Now func is a closure function, and the func function can be executed with parentheses
And we must know that the result of the func function will print the words "I like python", and the result will be the same no matter where the func function is called in the program
- The use of Global and Nonlocal in Python is detailed
- The difference between the Python keywords global and nonlocal is detailed
- Declaration and parsing of the Python keywords nonlocal and global
- Closure of python functions in detail (internal and external functions detailed)
- Write a simple and practical log decorator based on Python
- Python basic globlal nonlocal and closure function decorator syntax sugar
Related article
-
python data parsing BeautifulSoup crawl Three Kingdoms chapter example
This article mainly introduces the python data parsing BeautifulSoup chapter example, the article contains detailed example code, friends in need can use for reference, I hope to be helpful2021-09-09 -
How does Python crack the zip code
Crack rar and zip compression packages. Windows under the use of PyCharm software, this article gives you a detailed introduction to Python how to crack the compression package password, interested friends take a look2022-05-05 -
Python+OpenCV implements circle detection in images
This article mainly introduces how to use Python+OpenCV to detect the circle in the picture, the example code in the article explains in detail, interested partners quickly follow the small series together to learn2022-04-04 -
Python custom logger module instance code
The logging module in the Python standard library provides logging functions to customize the Logger Log recording can be customized according to the needs of the project to meet the specific log recording format, output target and log level requirements, this paper introduces the Python custom logger module instance code, need friends can refer to it2024-02-02 -
The Python shelve module implements parsing
This article mainly introduces the implementation of Python shelve module parsing, the article through the example code is very detailed, for everyone's study or work has a certain reference learning value, need friends can refer to it2019-08-08 -
Example of Python3 parsing and processing sound data
Today, Xiaobian will share an example of Python3 analysis and processing of sound data for you, which has a good reference value, and I hope to help you. Let's take a look2019-08-08 -
getattr method to get an object reference in Python
Today, Xiaobian will share a method for getting object references through getattr in Python, which has a good reference value, and I hope to help you. Let's take a look2019-01-01 -
Python recognizes barcodes in processed photos
This article mainly introduces Python identification and processing of barcode in photos, to help you better use python to process pictures, improve office efficiency, interested friends can understand2020-11-11 -
Fixed an issue where Python plt.savefig saved images with blank space
Today, Xiaobian will share a solution to the problem of Python plt.savefig saving a blank picture, which has a good reference value, and I hope to help you. Let's take a look2019-01-01
Latest comments