The scope of variables in Python legb, closures, adorners basic understanding

Source: Internet
Author: User
Tags closure

First, Scope

creating, changing, and locating variable names in a Python program is done in a space where variable names are stored, which we call namespaces, also known as scopes. The scope of the Python is static, and the location of the variable name assigned to it in the source code determines the range to which the variable can be accessed. That is, the scope of the Python variable is determined by the position in the source code where the variable resides.

Not all statement blocks in Python will have scopes. Only when a variable is defined in module, Class (Class), Def (function), does it have the concept of scope. The scopes are not generated in the if, for, and while statements.

The local scope of the L (local), which exists in the scope of the locality within Def, is generated as the function is defined.

E (enclosing) nested scopes, in contrast to the L scope, when there is a function nesting, the scope of the intrinsic function is called the L scope, and the external function is called the E-scope.

G (global) global scope, where the variable is scoped within the module, can be easily understood as a range within a single file.

B (built-in) built-in scopes, variables defined within the system's fixed modules, such as predefined variables within the Builtin module, the highest level scope, the widest range, can be understood as the scope of the current operating system.

To illustrate:

#!/usr/bin/env Python3
#-*-Coding:utf-8-*-
__author__ = "Ask to Program"
__date__ = "2018-06-13 15:40"
Passline =   #global var

def func (Val):
    Passline =   #for func, it ' s local var;for in_func, it's enclosing var
    If Val >= passline:
Print "Pass"
Else
Print "Fail"
Def in_func ():
Print Val
Return In_func

def Max (Val1, Val2):
Return Max (Val1, Val2) # max is a built-in fun, functions can also be assigned to variables, so the scope of all built-in functions is visualized as B

Declaring Global variables:

A = 100
def foo ():
Global a # refers to a globally variable and recognizes its modified value
A = 200
Print (a)
Foo ()
Print (a)
---------
100
200
second, closed package

First understand the functions in Python, in Python, the function is an object (which can be viewed through the type function), takes up space in memory, and the internal variables are reclaimed by the interpreter after the execution of the function, but if a variable is returned, it is not recycled because the value of the reference counter is not 0 Since the function is also an object, he has his own property, and for a Python function, the return is not necessarily a variable, it can also be a function.

This leads to the concept of closure, when there is a function nesting (as in the previous example, Func () and In_func () are nested relationships), the return value of the external function is an intrinsic function, and the intrinsic function refers to the variables of the external function, parameters, and the referenced variables, parameters encapsulated together in the function as the return value, The intrinsic function is called a closure.

The necessary conditions for the formation of closures:

1) There must be an inline function (the function defined in the function)-this corresponds to the nesting of functions between
2) inline functions must refer to a variable defined within a closed range (external function)--an intrinsic function that references an external variable
3) The external function must return an inline function--the intrinsic function must be returned

Three, closure of the use of the scene

A first example:

#!/usr/bin/env Python3
#-*-Coding:utf-8-*-
__author__ = "Ask to Program"
__date__ = "2018-06-13 15:53"

Def funx ():
X=5 # for Funx, is the L-scope, for Funy, is the e-scope
Def funy (): # is a closed package
nonlocal x # bound to external X, only used in Python3
X+=1
return x
Return Funy

A = Funx ()
Print (A ())
Print (A ())
Print (A ())
Print (x)
-------------------------
6
7
8
Nameerror:name ' x ' is not defined

Originally X is only a local variable of funx (), but after a closure, it behaves as if it were a global variable, and the last error indicates that X is not a global variable. In fact, this is a very simple closure of the role, after the closure, the closure variable can be updated with the closure function calls, as if it were a global variable.

The second example is the most common example of closures:

Def func_150 (val):   # Total divided into 150, passing score of 90
Passline = 90
If Val >= passline:
Print "Pass"
Else
Print "Fail"

Def func_100 (val): # Total divided into 100, passing score of 60

If Val >= passline:
Print "Pass"
Else
Print "Fail"

FUNC_100 (89)
FUNC_150 (89)

Use closures to optimize the above code:

def set_passline (passline):
DEF CMP (val):
If Val >= passline:
Print "Pass"
Else
Print "Fail"
Return CMP

f_100 = set_passline # f_100 calls the function Set_passline () and assigns 60 to the variable passline, which is the return value of the f_100 equals function, which is the function CMP
f_150 = Set_passline (90)
F_100 () # f_100 () =cmp (), assign 89 to Val, run the CMP () function, output the result
F_150 (89)

A third example:

def my_sum (*arg):
Print (' In my_sum,arg= ', ARG)
return sum (ARG)


def Dec (func):
def in_dec (*arg):
Print (' In in_dec,arg= ', ARG)
If Len (arg) = = 0:
return 0
For Val in ARG:
If not Isinstance (val, int):
return 0
return func (*arg)

Return In_dec


my_sums = Dec (my_sum) # named My_sums, for the purpose of distinguishing it from the my_sum, for easy understanding
#① calls the DEC () function, assigning the return value of Dec to My_sums, equivalent to My_sums=in_dec,② assigning the function my_sum to Func, equivalent to Func=my_sum
result = My_sums (1, 2, 3, 4, 5)
#③ is equivalent to assigning (1, 2, 3, 4, 5) to Arg in the IN_DEC function, invoking and executing the function in_dec (),
The return value of the #④in_dec () function is the Func () function, which assigns ARG in the IN_DEC function to Arg in the Func () function, which is the value of ARG in My_sum ().
#⑤ calls and executes the function my_sum (), returning the sum (ARG) result to the variable result
Print (Result)
------------
In in_dec,arg= (1, 2, 3, 4, 5)
In my_sum,arg= (1, 2, 3, 4, 5)
15
The entire process can be simply understood as running the DEC () function First, its return value is the IN_DEC function, and then the In_dec function, whose return value is the Func function, the My_sum function, and then the My_sum function.
Dec (), In_dec (), My_sum ()

A fourth example:

#!/usr/bin/env Python3
#-*-Coding:utf-8-*-
__author__ = "Ask to Program"
__date__ = "2018-06-13 17:08"

variable = 300

Def test_scopt ():
Print (variable) # variable is a local variable of test_scopt (), but does not bind a memory object when printing.
Variable = $ # Because of this, so variable is changed to local variables

Test_scopt ()
Print (variable)
------------
unboundlocalerror:local variable ' variable ' referenced before assignment

The above example will report an error because the precompilation in the execution of the program can find the local variable variable (assigned to the variable) in test_scopt (). Variable names are found in the local scope, so they are not upgraded to nested scopes to look for. However, when you print the variable variable using the PRINT statement, the local variable variable and has not been bound to a memory object (there is no definition and initialization, that is, there is no value assigned). In essence, the LEGB rule followed by Python's invocation of a variable and the compiler principle of the Python parser determine the error. Therefore, before calling a variable, you need to assign a value to the variable (bind a Memory object).
Note: Why the error that is triggered in this example is unboundlocalerror instead of nameerror:name ' variable ' is not defined. Because the variable variable is not in the global scope. The module code in Python is not precompiled until it is executed, but the function body code inside the module is pre-compiled before it runs, so the compiler knows whether the binding of the variable name takes place in the scope. Although Python is a static-scoped language, variable name lookups occur dynamically, and only when the program runs does it discover scope issues

You can use global to declare a variable variable as a global variable.

four, decorative device

A conceptual knowledge, a clumsy expression:

1. The decorator is the use of closures;
2. The function of the adorner is the decoration function;
3. The adorner returns a function object, which is received by the decorated function;
4. The decorated function identifier points to the returned function object.

Use the third example above to add an adorner:

def Dec (func):
def in_dec (*arg):
Print (' In in_dec,arg= ', ARG)
If Len (arg) = = 0:
return 0
For Val in ARG:
If not Isinstance (val, int):
return 0
return func (*arg)
Print (' in Dec ') # New Line
Return In_dec

def my_sum (*arg):
Print (' In my_sum,arg= ', ARG)
return sum (ARG)
Print (Type (my_sum))

To instantiate a concept:

1,@dec is an adorner, is called the DEC () function to form the adorner;

2. The decorated function is my_sum (), that is, when the DEC () function is called to form the adorner, the DEC () function has the my_sum () function, namely: Func = My_sum

3, the return value of the adorner is the function In_dec (), the return value is received by the function my_sum (), is actually passed to the decorated function (that is, the my_sum () function) identifier my_sum, namely: My_sum=in_dec

Run the file directly, output:

--------------
In Dec
<class ' function ' > # At this point My_sum does not refer to the Def my_sum (*arg) function defined, but instead to the return value of the adorner, the IN_DEC function.

Note that the function in the adorner is invoked whenever the adorner is used, and the return value of the adorner: In_dec (), received by the my_sum (if no return in_dec, run directly, the my_sum format is: <class ' nonetype '; Indicates that when the adorner does not return a value, none is returned, as is the function).

Next, execute the statement:

result = My_sum (1, 2, 3, 4, 5)  
Print (Result)
------------
In Dec
<class ' function ' >
In in_dec,arg= (1, 2, 3, 4, 5)
In my_sum,arg= (1, 2, 3, 4, 5)
15

The running process is (in conjunction with a third example):

1, @dec, call the DEC function, its parameters are decorated function my_sum (), that is, Func=my_sum, execute print (' in Dec '), return the In_dec function, is My_sum received, that is: The final function in_dec the results of the operation, The identifier My_sum is passed to the decorated function;

2, call In_dec function, parameter is (1,2,3,4,5), execute print, if, for statement, execute return func (*arg), func=my_sum function;

3, call the function my_sum (), the parameter is (1,2,3,4,5), execute the PRINT statement, execute return sum (*ARG), return the final result;

Reference article:

Https://www.cnblogs.com/fireporsche/p/7813961.html

Https://www.cnblogs.com/cotyb/p/5243252.html

The scope of variables in Python legb, closures, adorners basic understanding

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.