In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-21 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly shows you the "Python closures and free variables in the use of methods and matters needing attention", the content is easy to understand, clear, hope to help you solve your doubts, the following let the editor lead you to study and learn about "Python closures and free variables in the use of methods and precautions are what" this article.
1. Define
Define another function inside the function, and this function uses the variable of the external function (LEGB), and finally returns the function name index of the new function, then the function that can access the scope of its definition and some variables used are called closures. A referenced non-global variable is also called a free variable. This free variable is stored in the read-only property _ _ closure__ of the external function and will have a binding relationship with the inner function, that is, the free variable will not easily disappear in memory. As shown in the following example:
# calculate the number of times the function is called def counter (FIRST=0):-_ _ closure__- | cnt = [FIRST] | # the list is selected because of the scope problem For details, see later | def add_one (): | | cnt [0] + = 1 | | return cnt [0] |- -- return add_one# whenever an external function is called The internal function will be redefined, and the value of the variable cnt may be different num5 = counter (5) num10 = counter (10) print (num5 ()) # 6print (num5 ()) # 7print (num10 ()) # 11print (num10 ()) # 1 if the function is only nested Then its _ _ closure__ should be Noneprint (num5.__closure__) # (,) print (num5.__closure__ [0] .cell _ contents) # 7print (num10.__closure__ [0] .cell _ contents) # 1 or check whether there is a free variable in the function through _ _ code__.co_freevars. If there is a free variable, it is the closure print (num10.__code__.co_freevars) # ('cnt') ) 2.nonlocal keyword
The cnt variable in the above code is a list, mutable object, but what if it is an immutable object, such as numer, tuple, etc.?
Def counter (FIRST=0): cnt = FIRST # number def add_one (): cnt + = 1 return cnt return add_onenum5 = counter (5) print (num5.__closure__) print (num5.__code__.co_freevars) print (num5 ())- -def counter (FIRST=0): cnt = (FIRST ) # tuple def add_one (): cnt [0] + = 1 return cnt [0] return add_onenum5 = counter (5) print (num5.__closure__) print (num5.__code__.co_freevars) print (num5 ())
The output result of the above example:
None () Traceback (most recent call last): File "test.py", line, in print (num5 ()) File "test.py", line In add_one cnt + = 1UnboundLocalError: local variable 'cnt' referenced before assignment---- (,) (' cnt',) Traceback (most recent call last): File "test.py", line In print (num5 ()) File "test.py", line, in add_one cnt [0] + = 1TypeError: 'tuple' object does not support item assignment
As you can see, cnt is no longer a free variable, but becomes a local variable, and prompts UnboundLocalError that it is not bound with a local error. Why is it not a free variable? Why is the list not a problem?
This is because Python does not require a variable to be declared before it can be used. The Python interpreter believes that as long as a variable is assigned to a function, then the variable is a local variable.
The module code of Python is not precompiled before it is executed, and the function body code within the module is precompiled before it is run, so no matter where the binding of the variable name occurs in the scope, the compiler can know it.
Cnt+ = 1 is equivalent to cnt = cnt+1, and the cnt is assigned, so the Python interpreter thinks that cnt is a local variable within the function, but when it is executed, it is found when the cnt+1 is executed first:
Because cnt has been previously identified as a local variable, now can not find the value of cnt in the local scope, will no longer find the external scope, it will report an error. So cnt is no longer a free variable.
What about cnt of type tuple? First of all, cnt [0] = cnt [0] + 1, although there is an assignment, the left side is also cnt [0], and cnt is indexed from the outside scope.
So, you see what it shows: at this time, cnt is indeed a free variable, but it is an immutable object, so a TypeError error is reported. You should know why this list works.
Or you use the nonolocal keyword, which is used much like global, allowing you to assign values to variables in an external scope (non-global scope). It can make an assigned local variable a free variable, and when the variable declared by nonlocal changes, so does the value stored in _ _ closure__:
Def counter (FIRST=0): cnt = FIRST # number def add_one (): nonlocal cnt cnt + = 1 return cnt return add_onenum5 = counter (5) print (num5.__closure__) print (num5.__code__.co_freevars) print (num5 ()) (,) ('cnt',) 6
Nonlocal and global
Def scope_test (): spam = "test spam" def do_nonlocal (): nonlocal spam spam = "nonlocal spam" def do_global (): global spam spam = "global spam" do_nonlocal () print ("After nonlocal assignment:", spam) # nonlocal spam do_global () print ("After global assignment:" spam) # nonlocal spam scope_test () print ("In global scope:" Spam) # global spamAfter nonlocal assignment: nonlocal spamAfter global assignment: nonlocal spamIn global scope: global spam3. Matters needing attention
The pit of lambda free parameters, especially when used in conjunction with list parsing or for loops. Lambda para_list: expression = = > def (para_list): return expression
#-CASE1fs = [lambda j:i*j for i in range (3)] print ([f (2) for f in fs]) #-CASE2fs = map (lambda I: (lambda j:i*j), range (3)) print ([f (2) for f in fs]) #-CASE3fs = [(lambda i:lambda j:i*j) (I) for i in range (3)] print ([f (2) for f in fs]) [4,4,4] [0,2,4] [0 2, 4]
First of all, CASE1 and CASE3 obviously add a lambda function to the list every time they loop. The difference is that the I in the lambda function added by CASE1 does not receive the value of I in the for loop, it just refers to the next I when it is defined, so the I of several lambda functions in CASE1 is the last time it is called, that is, f (2), it looks for its value in the outer scope. The value of I found at this time is the value of I at the end of the for loop. CASE3 assigns an initial value to I as soon as it is defined and added. CASE2 is because map passes an iterable object element to I during each iteration, so the I of each lambda function in CASE2 also has its own value.
If you don't mean to do this, you'd better switch to the default parameter if you don't want to do this on purpose, such as the free parameter of lambda:
Fs = [lambda x: Xampi for i in range (3)] print ([f (2) for f in fs]) fs = [lambda x, iTuni: Xonomi for i in range (3)] print ([f (2) for f in fs]) [4,4,4] [2,3,4]
In addition, the scope in list parsing is a whole new scope, which is different from the normal for loop:
#-CASE4fs = [lambda j:i*j for i in range (3)] print ([f (2) for f in fs]) I = 4print ([f (2) for f in fs]) #-CASE5fs = [] for i in range (3): fs.append (lambda j:i*j) print ([f (2) for f in fs]) I = 4print ([f (2) for f in fs]) [10, 10, 10] [10, 10, 10] [8, 8] 8] 4. Working with scen
Decorator
Lazy evaluation is more common when accessing the database, you can refer to the implementation of Django's queryset
If you need to assign a value to the parameters of a function in advance, you can also use the partial function of functools.parial: functools.partial (func, * args, * * kw) to return a partial function object.
# y = aplyx + b, an and b may appear only once, x will appear multiple times def line (a, b, x): return aplasx + bprint (line (3,4,5)) print (line (3,4,6)) print (line (7,4,5)) print (line (7,4,6)) # 2. Use the closure def line (a, b): def value (x): return axix + b return value# y = 3x + 4line1 = line (3,4) print (line1 (5)) print (line1 (6)) print (line1 (7)) # y = 9x + 7line2 = line (9,7) print (line2 (5)) print (line2 (6)) print (line2 (7)) # 3. Use the functools.partial partial function from functools import partialline3 = partial (line, 3) print (line3) # functools.partial (, 3) print (line3 (4,5)) line4 = partial (line, 3,4) print (line4 (5) print (line4 (6)) print (line4 (7) line5 = partial (line, 9,7) print (line5 (5)) print (line5 (6)) print (line5 (7))
To sum up, the purpose of functools.partial is that it can fix some parameters of a function (that is, set default values) and return a new function, which is easier to call.
These are all the contents of the article "what are the usage and precautions of closures and free variables in Python?" Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.