Python advanced-Namespaces and scopes
Write in front
If not specifically stated, the following are based onPython3
Namespaces are associated with binding to names, and can be combined with another article that introduces Python
names, objects, and bindings.
1. Namespaces
1.1 What is a namespace
Namespace
namespaces, also called namespaces, are mappings from names to objects. Python
, most of the namespaces are implemented in dictionaries, but the implementation of namespaces is not involved in this article.
One of the major functions of namespaces is to avoid name collisions:
Def fun1 (): i = 1def fun2 (): i = 2
Of the two functions in the same module, i
there is absolutely no relationship between two names of the same name, because they belong to different clear spaces.
1.2 Types of namespaces
The common namespaces are:
built-in
A collection of names, including abs()
functions like this, as well as built-in exception names. In general, use the word built -in to represent this namespace- built-in namespaces
Module Global name collection, directly defined in the module name, such as classes, functions, imported other modules and so on. Typically, a global namespace representation is used.
The name collection in the function call procedure, the parameters in the function, the name of the function body definition, etc., are "activated" when the function is called, constituting a namespace. Typically, a local namespace representation is used.
A collection of properties for an object, which also forms a namespace. However, objname.attrname
the indirect way of accessing properties, rather than direct access, is usually used, so it is not included in the namespace discussion.
Class, a new namespace is created when the interpreter enters the class definition and executes to the class ClassName:
statement. (See official description of the class definition)
1.3 Life cycle of namespaces
Different types of namespaces have different lifecycles:
Built-in namespaces, Python
created when the interpreter starts, and destroyed when the interpreter exits;
Global namespace, where the module's global namespace is created when the module definition is read by the interpreter and destroyed when the interpreter exits;
Local namespaces, where you distinguish between functions and class definitions. The local namespace of the function, created when the function is called, or destroyed by an uncaught exception, the namespace defined by the class, which is destroyed when the interpreter reads the class definition creation and the class definition ends. (about the namespace defined by the class, destroyed after the end of the class definition, but actually the class object is the wrapper for the namespace content, see official description of the class definition)
2. Scope
2.1 What is a scope
The scope is a Python
piece of text area in which the namespace can be "directly accessed". Direct access here refers to an absolute reference (unqualified reference) that attempts to find the name in the namespace. It is necessary to explain the following direct and indirect references :
A direct reference to the way the name is accessed directly, such as attempting to search for a name
name in the namespace name
.
Indirect reference; Use a form objname.attrname
-by-property reference, which does not search for a name in a namespace, attrname
but instead searches for a name objname
and then accesses its properties.
2.2 Relationship to namespaces
Now, the namespace holds the name. The scope is a piece of text area, that is, a Python
piece of code area, need code region reference name (access variable), then the inevitable scope and namespace have a connection.
As the name implies, the names scope is the area of code text that the name can affect, and the scope of the namespace is the area of code text that the namespace can affect. Then there is a code text area where multiple namespaces can affect it.
The scope is only the text area, its definition is static, and the namespace is dynamic, and the namespaces are generated only as the interpreter executes. Then, the name in the dynamic namespace is accessed in a static scope, causing the dynamic nature of the scope usage.
Well, you can think of it this way:
A static scope is one or more namespaces that affect the area of code by a certain number of rules, and runtime dynamic scopes are namespaces that are combined by a particular level.
To some extent, a dynamic scope is considered a namespace. In the following statement, I will equate dynamic scopes with their corresponding namespaces.
2.3 Name Search Rules
A name is quoted in the program, Python
how does it search for that name?
At least three namespaces can be accessed directly when the program is running:
Local
The first search, which contains the inner (innermost) scope of the local name, such as the internal local scope of the function/method/class;
Enclosing
The scope of any enclosing function that contains a non-local (nonlocal) non-Global (Nonglobal) name, based on a nested hierarchy, searching from inside out. As two nested functions, the scope of the inner function is local scope, and the outer function scope is the enclosing scope of the inner layer function;
Global
The second countdown is searched, containing the scope of the current module global name;
Built-in
The last one is searched, containing the outermost scope of the built-in name.
When the program runs, LGB
there are three scopes that must exist, and the scope does not E
necessarily exist; If the program is:
i = 1print (i)
Where is the local scope? We think (Python Scopes and namespaces):
Usually, the local scope references the local names of the (textually) current function. Outside functions, the local scope references the same namespace as the Global scope:the module ' s namespace. Class definitions Place yet another namespace in the local scope.
In general, local scopes refer to the names defined in the function. Functions, local scopes and global scopes refer to the same namespace: The star space of the module. However, the local scope of the type refers to the class definition new namespace.
Python
L-E-G-B
search for names in four scopes in the order above. Throws an exception when no search is reached Python
NameError
.
2.4 When to introduce scopes
We know:
Python
a name can be referenced only after it has been defined.
Print (i)
Directly referencing an undefined name i
, according to the search rule, LGB
No name i
(the same namespace) is searched for three scopes LB
. Throw NameError
Exception:
Traceback (most recent): File "scope_test.py", line <module> print (i) Nameerror:name ' I ' are Not defined
What about this piece of code?
Def try_to_define_name (): The function defines the name I, and binds an integer object 1 " i = 1try_to_define_name () print (i) #引用名字i之前, called the function
Before referring to the name i
, obviously called the function, defined the name i
, but still can not find the name:
Traceback (most recent): File ' scope_test.py ', line <module> print (i) #引用名字i之前, Called the function nameerror:name ' I ' is not defined
Although the name is defined, it is i
defined in the local namespace corresponding to the local scope of the function, and according to the LEGB
search rules, the local scope is not accessible in the global scope; Moreover, after the function call is finished, the namespace is destroyed.
The reference name is always related to the scope, so:
Python
a name can be referenced in the appropriate scope only after it has been defined.
Then, when defining a name, you should pay attention to the scope of the name definition, so as not to be found when the definition requires access. Therefore, Python
it is necessary to know when a new scope will be introduced. In general, the B,G
introduction of two scopes in a scope that cannot be manipulated by code is only possible through the introduction of a statement E,L
. The Python
statements introduced in the new scope are very limited, and in general there are only two categories:
function definitions introduce scopes local
or scopes Enclosing
; in essence, lambda
and generator expressions are functions that introduce new scopes.
Class definition introduces local
scope;
List derivation Introduction local
scope, legend in the python2
list derivation does not introduce a new scope
Some of the most confusing places for apes with other high-level language experiences:
if
Statement :
If True: i = 1print (i) # output:1, not Nameerror
if
The statement does not introduce a new scope, so the name binding i = 1
statement print(i)
is in the same scope.
for
Statement :
For I in range (6): passprint (i) #output: 5 instead of Nameerror
for
The statement also does not introduce a new scope, so i
the name is bound and re-bound with print(i)
the same scope. This Python
is a bit more pit, so write code for
should not cycle the name to the other names do not have the same name.
import
Statement :
Def import_sys (): ' import sys module ' ' import Sysimport_sys () print (sys.path) # nameerror:name ' sys ' is not Defined
This is not normal programmer's writing, in another article, "Python Advanced-object, name and binding," described in the function of the import
import_sys
name sys
and corresponding module binding, the sys
name is still defined in the local scope, There is no task difference with the example above. To always remember Python
the name, object, this other programming language is not the same, but:
The second programming language that breaks the first programming language cognition is a good language that is worth learning.
3. Scope Application
3.1 Free variable readable and non-writable
I don't really want to use the word "variable" to describe a name, but the variable is a well-known, Python
free variable:
If A variable is used in a code block and not defined there, it's a free variable.
If the code block where the reference occurs is not where it is defined, it is a free variable. A professional point is:
The name is not in the scope of the reference name, and the name is a free name.
Note: "Free name" is only the author yy, and has not been widely recognized.
We have learned the LEGB
hierarchy of scopes and searched for names sequentially. In search order, when a lower scope does not have a name to search for, a name that refers to a high-level scope exists, that is, a free name:
[Example 1]
Def low_scope (): print (s) s = ' upper scope ' low_scope ()
It is clear that the output of this code is upper scope
.
[Example 2]
Def low_scope (): s = ' lower scope ' s = ' upper scope ' Low_scope () print (s)
Unfortunately, the final print statement didn't print as expected lower scope
upper scope
.
A Special quirk of Python is that–if no global statement are in effect–assignments to names all go into the Innermos T scope.
Python
One quirk of this is that if you don't use a global
statement, an assignment to a name usually affects the inner-most scope.
That is, the assignment statement affects the local scope, the effect of the assignment statement is binding or rebinding, but there is no name in the namespace of the current local scope, s
so the assignment statement is used locally to define the name of the same name s
, which s
does not conflict with the outer scope. Because they belong to different namespaces.
In this way, the global scope is s
not re-bound, and the result is well explained.
When a mutable object is involved, the situation is different:
[Example 3]
Def low_scope (): l[0] = 2l = [1, 2]low_scope () print (L) # [2, 2]
Unfortunately, the final print statement did not follow the expected output [1, 2]
but output [2, 2]
.
The experience of the previous example cannot be applied here because, list
as a mutable object, it l[0] = 2
is not a re-binding of the name l
, but rather a re-binding of the l
first element, so no new name is defined. Therefore, the value of the referenced object in the global application is successfully updated in the function l
.
Note that the following example is not the same as above:
[Example 4]
Def low_scope (): L = [2, 2]l = [1, 2]low_scope () print (L) # [1, 2]
We can interpret it using the method in Example 1 in this section.
In conclusion, it can be considered that:
Free variables are readable and not writable.
3.2 global
andnonlocal
There is always a need to break the rules:
In the lower scope, you need to rebind the high-level role domain name, i.e., by a free name.
global
the statements and nonlocal
statements are then born of transport.
global_stmt:: = "global" identifier ("," identifier)*
The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers is to be interpreted as globals. It would is impossible to assign to a global variable without global, although free variables could refer to globals without Being declared global.
global
Statement is a declaration statement that applies to the current block of code. The identifiers listed are interpreted as global names. Although a free name can refer to a global
global name without being declared, it is not global
possible to bind a global name without using a keyword.
nonlocal_stmt:: = "nonlocal" identifier ("," identifier)*
The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope Excluding Globals. This was important because the default behavior for binding are to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope.
nonlocal
The statement causes the names listed to point to the name of the binding in the nearest enclosing function, not the global name. The default binding behavior searches for local scopes first. nonlocal
statements make it possible to rebind the names of outer function scopes in the inner function, even if the names of the same name exist in the global scope.
Classic examples of the official:
Def scope_test (): def do_local (): spam = ' local spam ' def do_nonlocal (): nonlocal spam # When the spam name is not present in the outer scope, nonlocal cannot define a spam = ' nonlocal spam ' # Free name Spam after nonlocal declaration, can do the re-binding operation, can be written. def do_global (): Global spam # Even if there is no definition of the name spam in the global scope, this statement can be defined in the global scope name spam spam = ' Global spam ' # The own variable spam after the global Declaration, can do the re-binding operation, can be written. spam = ' Test spam ' do_local () print ("After local assignment:", spam) # after local assignment:test SPAM
do_nonlocal () print ("After nonlocal assignment:", spam) # after nonlocal assignment:nonlocal spam do_ Global () print ("After global assignment:", spam) # After global assignment:nonlocal spamscope_test () print (' in Global scope: ", spam) # in global Scope:global spam
The author says no nonlocal
evil:
Def nest_outter (): spam = ' outer ' def nest_inner (): nonlocal spam1 spam1 = ' inner ' nest_inner () print (spam) nest_outter ()
Output:
File "scope_test.py", line nonlocal spam1syntaxerror:no binding for nonlocal ' spam1 ' found
4. Some pits
The author was confident enough to understand Python
the scope of a thorough understanding, but a large pile of pits are not touch-resistant.
4.1 Pit 1-unboundlocalerror
def test (): print (i) i = 1i = 2test ()
Output:
Traceback (most recent): file "scope_test.py", line, <module> Test () file "Scope_ test.py ", line +, in test print (i) unboundlocalerror:local variable ' i ' referenced before assignment
In fact i = 2
, it is understandable to ignore this statement in the global scope.
Usually, the local scope references the local names of the (textually) current function.
Python
For local scopes, the interpreter executes to print(i)
, i
not in the local scope. When the interpreter tries to continue executing the name defined later i
, the interpreter throws the exception by thinking that the code used a name before it was defined. If the interpreter finishes explaining the entire function and does not find the name i
, it will look up along the search chain LEGB
, and finally cannot find the throw NameError
exception.
4.2 Pit 2-local scope of the class
Class Test (object): i = 1 def test_print (self): print (i) T = Test () i = 2t.test_print ()
I'll ask everyone, what's this output?
Of course it will be out of the blue 2
, especially if people with other language experience are more confused.
As highlighted above:
What is the life cycle of a function namespace? The invocation begins, returns, or ends abnormally, although the method called is in the example, but is essentially a function that invokes the class.
What is the scope of the class namespace? The class definition begins and the class finishes defining the end.
When the class definition starts, a new namespace that belongs to the class is created and used as a local scope. After the class is defined, the namespace is destroyed, and there is no direct way to access the class i
(unless through indirect access: Test.i
).
The essence of a method invocation is a function call:
Class Test (object): i = 1 def test_print (self): print (i) T = Test () i = T.test_print () test.test_print (t) # Square How the method call was last converted to a function call
The function call begins with its scope and global scope having a subordinate relationship ( L
and G
), the function i
as a free name, and the last output 2
.
Therefore, you cannot confuse the location of the data members and function members in the class, always remember that the Python
two ways to access the references are:
Direct reference: Try to directly write the name name
reference name, Python
according to LEGB
the search scope of the way to search for the name.
Indirect reference: Use objname.attrname
the way to refer to the name attrname
, Python
do not search scopes, go directly to the object to find properties.
4.3 Pit 3-list derivation local scope
A normal-list derivation:
A = 1b = [A + I for I in Range]]print (b) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Now put the list deduction into the class:
Class Test (object): a = 1 b = [A + I for I in Range] print (b) def Test (self): Pass
Output:
Traceback (most recent): file "scope_test.py", line, <module> class Test (object): file "scope_test.py", line-up, in test B = [A + i-I in range]] File "scope_test.py", line at, in <listcomp> ; b = [A + I for I in range (Ten)]nameerror:name ' A ' is not defined
Output feedback name a
not defined.
As highlighted above, after the interpreter reads the class definition class ClassName
, the creation of namespaces is used as a local scope .
Statement a = 1
that defines the name in this local scopei
Statement b = [a + i for i in rage(10)]
, the list deduction similarly creates a local scope . This scope does not have a subordinate relationship to the local scope defined by the class, so there is no way to directly access a
the name.
Python
There are only four scopes: because the local scope of LEGB
the class definition and the local scope of the list deduction are not nested function relationships, they do not form a Enclosing
scope relationship. Therefore, they are two independent local scopes and cannot be accessed from each other.
Since it is a two independent local scope, the above example is equivalent to:
def test1 (): i = 1def test2 (): print (i) test1 () test2 ()
Expecting the test2
name to be visited in test1
i
, is obviously not feasible.
Reference
Python Scopes and namespaces
Python Namespaces and scopes snooping
Scope of Python
Naming and binding