This article mainly introduces a deep understanding of the namespace Search Rule LEGB in Python. The author will explain it based on Python3.x. If you need it, refer
Namespace
The Python namespace is a core component of Python.
In other languages, for example, C, the variable name is the alias of the memory address, while in Python, the name is a string object, which is associated with the object it points.
Python consists of many namespaces, while LEGB is a lookup rule for namespaces.
Scope
In Python, the name-object Association is stored in different scopes. different scopes are independent of each other. We search for name-object in different scopes.
For example, the scopes are independent of each other.
In [11]: i = "G"In [12]: def test(): i = "L" print i, "in locals" ....:In [13]: test() L in localsIn [14]: print i, "in globals" G in globals
In the preceding example, we define I twice. In the test function, I-L is used, and I-G is used outside. In the test function, why do I point to object L, while in the external function, I points to G? This is the role of LEGB.
Brief Introduction
In short, LEGB indicates the order in which names are queried: locals-> enclosing function-> globals-> _ builtins __
- Locals is the namespace in the function, including local variables and parameters.
- Enclosing the namespace of external nested functions (common in closures)
- Globals global variable, the namespace of the module where the function is defined
- Builtins built-in module namespace
Therefore, when retrieving a variable in Python, you should first return to locals for retrieval. If not, enclosing will be retrieved. If enclosing is not found, it will be retrieved from the globals global variable, finally, it is retrieved in builtins.
Of course, because of the special nature of builtins, we can directly add variables in builtins to access variables in any module. However, this method is too abnormal and is not recommended.
Locals, globals
The parameters and internal variables of the function are stored in locals.
In [1]: def f(x): ...: a = x ...: print a ...: print locals() ...:In [2]: f("hello")hello{'a': 'hello', 'x': 'hello'}
However, when the function calls the global declaration internally, the variables can be stored in globals.
In [6]: def f(x): ...: global a ...: a = x ...: print a ...: print locals() ...:In [7]: f("hello")hello{'x': 'hello'}In [8]: print ahelloIn [9]: print x---------------------------------------------------------------------------NameError Traceback (most recent call last)
in
()----> 1 print xNameError: name 'x' is not defined
As in the example above, if a is declared as a global variable in the function, the locals of function f only has the parameter x, but does not have the variable, and the variable a can be used externally, when using x, it is named error.
Enclosed
Enclosing is the namespace of an external nested function. We often use it in closures. In Python3, A nonlocal keyword is provided to modify the namespace of the external nested function, but only Python3 is required. I can only look at Python2 for a moment.
In [11]: def outer(): ....: a_var = 'enclosed value' ....: print a_var ....: def inner(): ....: a_var = 'local value' ....: print(a_var) ....: inner() ....: print a_var ....:In [12]: outer()enclosed valuelocal valueenclosed value
The following example shows how to use nonlocal. Python 3 can run normally:
In [1]: a_var = 'global value'In [2]: def outer(): ...: a_var = "local value" ...: print("outer befor", a_var) ...: def inner(): ...: nonlocal a_var ...: a_var = "inner value" ...: print("in inner():", a_var) ...: inner() ...: print("outer inner:", a_var) ...:In [3]: outer()outer befor local valuein inner(): inner valueouter inner: inner valueIn [4]: print(a_var)global value
Builtins
Builtins are built-in modules, so do not modify them easily.
In [19]: b---------------------------------------------------------------------------NameError Traceback (most recent call last)
in
()----> 1 bNameError: name 'b' is not definedIn [20]: __builtins__.b = "builtins"In [21]: bOut[21]: 'builtins'
In the preceding example, the NameError is reported when B is called for the first time. Then, we modify the builtins namespace and associate the name B with the value "builtins" to make the call normal. This unconventional usage is not recommended.