Introduction to closures in Python
Closure (Closure) is the abbreviation of lexical closure (lexical Closure), which is a function that references a free variable. The referenced free variable will exist with this function, even if it has left the environment that created it. Therefore, closures are entities that are composed of functions and reference environments associated with them.
Look at the namespace in Python before you begin to introduce closures.
The namespace in Python
Python by providing namespace to achieve duplicate functions/methods, variables, such as the identification of information, a total of three kinds of namespace, respectively:
Local namespace: scope is current function or class method
Global namespace: Scope is current module
Build-in namespace: scope for all modules
When the name of a function/method, variable, and so on is duplicate, Python searches for the required elements of the user in the order of "local namespace-> global namespace-> build-in namespace", and the first one to find the element namespace is the standard.
Also, built-in functions in Python locals () and Globals () can be used to view the elements defined in different namespace.
Look at an example:
s = "String in global" num = 99 Def numfunc (a, b):
num = 100 print "print s in numfunc: ", s def addfunc (a, b): s = "String in addfunc" print "print s in addfunc: ", s print "print num in addfunc: ", num print "locals of addfunc: ", locals () print return "%d + %d = %d " % (a, b, a + b) print " locals of numfunc: ", locals () print Return addfunc (a, b) numfunc (3, 6) print "globals: ", globals ()
The result of the above code is:
In the code, the elements defined in different namespace are obtained by locals () and Globals (), and when the s variable is accessed in the "Numfunc" function, the s in the global is found because there is not a definition of s in the local namespace; "Addfunc" has s in the local namespace, so it can be used directly.
Python Create closures
Here's a step-by-step example of how Python implements closures.
Example of a closure
The following is a simple example of a closure that defines a function called "greeting_conf", in which a "greeting" is embedded in the function:
def greeting_conf (prefix):
def greeting (name):
print prefix, name return
greeting
mgreeting = greeting_conf ("Good Morning")
mgreeting ("Wilber")
mgreeting ("'ll")
print
agreeting = Greeting_conf ("Good Afternoon")
agreeting ("Wilber")
agreeting ("would")
The result of the code is:
The above code has the following points to note:
The "greeting" function accesses the non-local variable "prefix", which is perfectly legal according to the previous namespace's introduction.
The variable "prefix" is not destroyed as the function exits, but the life cycle is extended.
Let's see why the variable "prefix" Life cycle has been extended?
__closure__ Property
In Python, the function object has a __closure__ attribute, and we can look at some of the closure details with this property.
def greeting_conf (prefix):
def greeting (name):
print prefix, name return
greeting
mgreeting = greeting_conf ("Good Morning")
print dir (mgreeting)
print mgreeting.__closure__
print type (m Greeting.__closure__[0])
print mgreeting.__closure__[0].cell_contents
Seen by the __closure__ property, it corresponds to a Tuple,tuple object that contains the cell type.
For this example, you can get the value of the cell (content) as "Good Morning", which is the value of the variable "prefix".
The principle of closure is seen here, and when the inline function references a variable in its function (enclosing function), the variables are stored in the __closure__ property of the enclosing function and become enclosing Part of the function itself; that is, the life cycle of these variables is the same as the enclosing function.
Closures and functions
Closures are just like functions in form, but they are not functions.
def greeting_conf (prefix):
def greeting (name):
print prefix, name return
greeting
mgreeting = greeting_conf ("Good Morning")
print "function name is:", mgreeting.__name__
print ID of Mgreet ' ing is: ', ID (mgreeting)
print
agreeting = greeting_conf ("Good Afternoon")
print "function name is:", AGree ting.__name__
print "ID of agreeting is:", ID (agreeting)
As you can see from the results of your code, a closure can have multiple instances at run time, and a different reference environment (here is the prefix variable) and the same function (here is greeting) can produce different instances.
How to create a closure in Python
Creating a closure in Python can boil down to the following three points:
The closure function must have an inline function
The inline function needs to refer to the variables in the first level namespace of the nested function
The closure function must return the inline function
With these three points, you can create a closure and think of the Python adorner described in the previous article. Yes, the Python decorator uses a closure.
Python instance
It's always a little confusing to look at the concept, so just look at a few Python examples.
Example 1
def make_adder (addend):
def adder (augend): return
augend + addend return
adder
p = Make_ad Der
q = make_adder (100) print P (m)
Run Result:
123
144
Analyze:
We found that the Make_adder is a function, including a parameter addend, the special place is that this function also defines a new function, the new function inside a variable is exactly the external make_adder parameters. In other words, The externally passed Addend parameters have been bound together with the Adder function, forming a new function, we can see addend as a new function of the configuration information, configuration information is different, function is not the same, that is, can be customized after the function.
Looking at the results of the run, we found that although P and Q were make_adder generated, different results were obtained because the configuration parameters were different and then the function of the same parameter was followed. This is the closure.
Example 2
def hellocounter (name):
count=[0]
def counter ():
count[0]+=1
print ' Hello, ', name , ', ', str (count[0]) + ' access! '
return counter
hello = hellocounter (' ma6174 ') hello () hello () hello ()
Execution Results
Hello, YSISL, 1 access!
Hello, YSISL, 2 access!
Hello, YSISL, 3 access!
Analysis of the
This program is more interesting, we can think of this program as a function to count the number of times a function. count[0] can be seen as a counter, the Hello function is not executed once, the value of count[0] plus 1. Maybe you have a question: why not just write count and use a list? This is a bug in Python2, and if you don't use a list, you'll report an error:
unboundlocalerror:local variable ' count ' Referenced before assignment. What does
mean? That is, conut this variable you have no definition of the direct reference, I do not know what it is, the program collapsed. So, again python3 inside, introduced a keyword: nonlocal, this keyword is what? is to tell the Python program that my count variable is externally defined, and you go outside and look for it. Then python goes to the outer function and finds the COUNT=0 definition and assignment, and the program executes normally.
Python3 Code
def hellocounter (name):
count=0
def counter ():
nonlocal count
count+=1
print ' Hello, ', Name, ', ', str (count[0]) + ' access! '
return counter
hello = hellocounter (' ma6174 ') hello () hello () hello ()
For the study of this problem you can refer to http://linluxiang.iteye.com/blog/789946
Example 3
def makebold (FN):
def wrapped (): Return
"<b>" + fn () + "</b>" return
wrapped
D EF makeitalic (FN):
def wrapped (): Return
"<i>" + fn () + "</i>" return
wrapped
@makebold
@makeitalic
def hello (): Return
"Hello World"
print Hello ()
Execution results
<b><i>hello world</i></b>
Simple analysis
What do you think? Is this program familiar? Isn't this a legendary decorator? Yes, this is the adorner, in fact, the adorner is a closure, we recall the concept of the adorner: function (parameters, return value, etc.) for processing, to generate a function enhanced version of a function. And looking at the concept of closures, this enhanced version of the function is not what we configure after the function? The difference is that the adorner's argument is a function or class that specializes in processing a class or function.
Python inside a lot of advanced features, such as adorners, generators, list push, closures, anonymous functions, and so on, the development of use, may achieve a multiplier effect!