Sebastian Raschka Writing
This is a short tutorial on implementing Python variable namespace and scope resolution using LEGB rules. The following sections will provide a short sample code block to illustrate the problem briefly. You can simply read this tutorial from beginning to the beginning, but I encourage you to execute these snippets. You can copy and paste the code snippets.
Target
? Namespaces and Scopes: Where does python look for variable names?
? Can we define or reuse variable names for multiple objects at the same time?
? In what way does Python search for different namespaces for variable names?
Introduction to Namespaces and scopes
name Space
In general, namespaces are simply a container for mapping names to objects. As you may have heard, all strings, lists, functions, classes, and so on in Python are objects. Thus, the "object-to-name" mapping allows us to access this object using the name already assigned to the object. For example, if we do a simple string assignment, we can pass: a_string = "Hello string", we create an object about "Hello string", and from this we can access it by its variable name a_string.
We can imagine a namespace as a Python dictionary structure, where the key of the dictionary represents its name and where the value of the dictionary represents the object itself (which is also how the namespace is currently implemented in Python), for example,
A_namespace = {' name_a ': object_1, ' name_b ': object_2, ...}
Now, the tricky part is that in Python we have multiple separate namespaces, and names can be reused by different namespaces (only objects are unique, for example,
A_namespace = {' name_a ': object_1, ' name_b ': object_2, ...
B_namespace = {' name_a ': object_3, ' name_b ': Object_4, ...}
For example, when we call a loop or define a function, it will create its own namespace. Namespaces also have different levels (so-called "scopes"), which we'll discuss in more detail in the next section.
Range
In the above chapters, we have learned that namespaces can exist independently, with each other and their structure at a certain level, which brings us "scope". The scope in Python defines a hierarchy when we search for namespaces for the named objects map.
For example, let's consider this piece of code:
i = 1
def foo():
i = 5
print(i, 'in foo()')
print(i, 'global')
foo()
1 global
5 in foo()
Here, we only define the variable name I two times, once in the Foo function.
Foo_namespace = {' I ': object_3, ...}
Global_namespace = {' I ': object_1, ' name_b ': object_2, ...}
So, if we want to print the value of the variable i, how does Python know which namespace to look for? This place requires Python's LEGB rules to be implemented, which we'll discuss in the next section.
Tips:
We can use the global () and local () functions if we want to print out the map of the dictionary's globals and locals.
resolving variable name ranges with LEGB rules
As we've seen, multiple namespaces can exist independently of each other, and they can contain the same variable names at different levels. "Scope" defines the level at which Python searches for a specific "variable name" for its related objects. Now, the next question is: How does Python search for different levels of the namespace before it finds the mapping of the object name?
The answer is: Python uses the LEGB rule, which is
built-in, local-to-closed, global
The arrows should point to the direction of the namespace hierarchy search order.
? Local can be inside a function or in a class method, for example.
? A closure can be its enclosing method, for example, one method is included in another method.
? Global refers to the highest level of execution of scripts, and
the built-in is a special name that Python retains for itself.
So, if a specific name: Object mapping cannot be found in the local namespace, the next enclosing namespace will be searched. If the search in the enclosing scope is unsuccessful, Python will go to the global namespace to search, and eventually it will search the built-in namespace (note: If the name is not found in any of the namespaces, the system will report Nameerror).
Note:
Namespaces can also be nested, for example if we import a module, or if we define a new class. In this case, we must use a prefix to access these nested namespaces. Let me illustrate this concept in the following code block:
import numpy
import math
import scipy
print(math.pi, 'from the math module')
print(numpy.pi, 'from the numpy package')
print(scipy.pi, 'from the scipy package')
3.141592653589793 from the math module
3.141592653589793 from the numpy package
3.141592653589793 from the scipy package
(This is why we must be aware of the fact that we are using "from a module import *" Because it is possible to overwrite the existing variable name when loading the variable name into the global namespace.) )
1. lg– Local and global scope
Example 1.1
As a warm-up exercise, let's first forget about enclosing (E) and built-in (B) in the LEGB rule, and take a look at LG----local and global scope.
What will the following code print
a_var = 'global variable'
def a_func():
print(a_var, '[ a_var inside a_func() ]')
a_func()
print(a_var, '[ a_var outside a_func() ]')
Reason:
We first call A_func (), which should be the print A_var value. According to the LEGB rule, this method will first see if the A_var is defined in the local scope (L). Because A_func () does not define its own a_var, it looks up the first-level global range (G) until the range defined before A_var.
Example 1.2
Now, let's define the variable A_var in both global and local scopes.
Can you guess what the following code will produce?
a_var = 'global value'
def a_func():
a_var = 'local value'
print(a_var, '[ a_var inside a_func() ]') a_func()
print(a_var, '[ a_var outside a_func() ]')
Reason:
When we call A_func (), first it looks for A_var in the local scope (L), because A_var is already defined in the local scope a_func, and its assignment to local varible is printed. Note that this does not affect global variables in different scopes.
It is also possible to modify the global, for example, if we use the Global keyword when we re-assign a value. The following example shows:
a_var = 'global value'
def a_func():
global a_var
a_var = 'local value'
print(a_var, '[ a_var inside a_func() ]')
print(a_var, '[ a_var outside a_func() ]')
a_func()
print(a_var, '[ a_var outside a_func() ]')
But we must be careful in this order: if we do not explicitly tell Python that we want to use global scope to try to modify the value of the variable, it is easy to unboundlocalerror error. (Remember, the assignment action first performs the action on the right).
2. leg– local, closed and global range
Now, let's introduce the concept of enclosing scope (E). Can you guess what the following code will print, according to the order of "local, closed, global"?
Reason:
Let's quickly summarize what we're doing: we call outer (), whose variable a_var is locally defined (A_var exists globally). Next, the outer () function call also defines the inner () function of the variable named A_var. The print () function in Inner () finds (l->e) in the local scope before its scope hierarchy, so it prints the values assigned in the local scope.
Similar to the concept of the global keyword that we have seen in the previous chapters, we can use the keyword nonlocal, which is included in the built-in function, to explicitly access the outer (enclosing) scope of the variable to modify its variable value.
Note The Nonlocal keyword has been added to Python 3.x and has not been implemented in Python 2.x.
3. legb– partial, closed, global, built-in
Summarize the LEGB rules and let's get into the built-in range. Here, we define the length function of our "own", which exactly has the same name as the built-in Len () function. If we execute the following code, what is the result?
Reason:
Because the same name can be used to map different objects, as long as the name is in a different namespace and there is no reuse of the name to define its own function Len length problem (this is only for demonstration, not recommended). When we review Python's L->E> G > B levels, Function A_func () discovers that Len () is already in global scope (G) before it attempts to search the built-in (B) namespace.
Conclusion
I hope that this short tutorial will help you understand the basic concepts of Python using LEGB rules for the order of scope parsing. I want to encourage you (to do a little free exercise) go to the Code section tomorrow and check to see if you can predict their results correctly.
Rule of thumb
In practice, modifying global variables in the scope of a function is often a bad idea because it often causes confusing and strange errors and is difficult to debug.
If you want to modify a global variable through a function, it is recommended that you pass the parameter to the global variable and reassign the return value to the global variable.
WARNING: Join the global namespace for the loop variable "leaking"
Instead of becoming a language, For-loops will use the scope of their existence and leave the cyclic variables they have defined.
This is also used if we explicitly define the FOR-LOOP variable before the global namespace! In this case, it will rebind the existing variable.
However, in Python 3.x , we can use closures to prevent loop variables from splitting them into the global namespace.
Why do I mention "Python 3.x"? Because when the problem occurs, the same code in Python 2.x executes the result:
English Original: http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html
The naming space, scope resolution and LEDB rules for beginners ' tutorials