Python3 Namespace and Scope

Namespace

First, let's look at a passage from the official documentation:

A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries。

A namespace is a mapping from names to objects. Most namespaces are currently implemented as Python dictionaries.

Namespaces provide a way to avoid name conflicts in projects. Each namespace is independent and has no relationship with others, so a single namespace cannot have duplicate names, but different namespaces can have the same name without any effect.

Let's take an example from a computer system: a folder (directory) can contain multiple folders, and each folder cannot have files with the same name, but files in different folders can have the same name.

There are generally three types of namespaces:

  • Built-in names (built-in names), names built into the Python language, such as function names abs, char, and exception names BaseException, Exception, etc.
  • Global names (global names), names defined in a module, recording the module's variables, including functions, classes, other imported modules, and module-level variables and constants.
  • Local names (local names), names defined in a function, recording the function's variables, including function parameters and locally defined variables. (Those defined in a class are also included.)

Namespace lookup order:

Suppose we want to use the variable example, then Python's lookup order is:Local namespace -> Global namespace -> Built-in namespace。

If the variable example is not found, it will give up the lookup and raise a NameError exception:

NameError: name 'example' is not defined。

The lifecycle of a namespace:

The lifecycle of a namespace depends on the scope of the object. If the object has finished executing, the lifecycle of that namespace ends.

Therefore, we cannot access objects in an inner namespace from an outer namespace.

Example

# var1 is a global name
var1 = 5
def some_func():
 
    # var2 is a local name
    var2 = 6
    def some_inner_func():
 
        # var3 is a nested local name
        var3 = 7

As shown in the figure below, the same object name can exist in multiple namespaces.


Scope

A scope is a textual region of a Python program where a namespace is directly accessible. "Directly accessible" here means that an unqualified reference to a name attempts to find the name in the namespace.

A scope is the textual region of a Python program where a namespace is directly accessible.

In a Python program, directly accessing a variable will access all scopes from inner to outer until it is found; otherwise, an undefined error will be reported.

In Python, a program's variables cannot be accessed from just any location; access permissions depend on where the variable is assigned.

The scope of a variable determines which part of the program can access a particular variable name.

Python has a total of 4 scopes, which are:

There are four scopes:

  • L(Local): The innermost layer, containing local variables, such as inside a function/method.
  • E(Enclosing): Contains variables that are non-local (non-local) and also non-global (non-global). For example, with two nested functions, if a function (or class) A contains another function B, then for names in B, the scope in A is nonlocal.
  • G(Global): The outermost layer of the current script, such as the global variables of the current module.
  • B(Built-in): Contains built-in variables/keywords, etc., searched last.

LEGB rule (Local, Enclosing, Global, Built-in): The order in which Python looks up variables is:L –> E –> G –> B。

  1. Local: The local scope of the current function.
  2. Enclosing: The scope of the outer function that contains the current function (if there are nested functions).
  3. Global: The global scope of the current module.
  4. Built-in: Python's built-in scope.

If not found locally, it will search in the enclosing local scope (e.g., closures); if still not found, it will search in the global scope, and then in the built-in scope.

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域

The built-in scope is implemented through a standard module named builtin, but the variable name itself is not placed in the built-in scope, so you must import this file to use it. In Python 3.0, you can use the following code to see exactly which variables are predefined:

>>> import builtins
>>> dir(builtins)

In Python, only modules, classes, and functions (def, lambda) introduce new scopes. Other code blocks (such as if/elif/else, try/except, for/while, etc.) do not introduce new scopes. That is, variables defined inside these statements can also be accessed externally, as in the following code:

>>> if True:
...  msg = 'I am from Example'
... 
>>> msg
'I am from Example'
>>> 

In the example, the variable msg is defined in an if statement block, but it can still be accessed externally.

If msg is defined inside a function, then it is a local variable and cannot be accessed externally:

>>> def test():
...     msg_inner = 'I am from Example'
... 
>>> msg_inner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>> 

From the error message, it indicates that msg_inner is undefined and cannot be used, because it is a local variable and can only be used inside the function.

Global and Local Variables

Variables defined inside a function have a local scope, and those defined outside a function have a global scope.

Local variables can only be accessed inside the function where they are declared, while global variables can be accessed throughout the entire program.

Variables declared inside a function are only valid in the scope within the function. When the function is called, these internal variables are added to the function's internal scope and do not affect variables of the same name outside the function, as in the following example:

Example (Python 3.0+)

#!/usr/bin/python3 total = 0 # This is a global variable # Writable function description def sum( arg1, arg2 ): # Returns the sum of two parameters. total = arg1 + arg2 # total is a local variable here. print ("Inside the function, it is a local variable:", total) return total # Call the sum function sum( 10, 20 ) print ("Outside the function, it is a global variable:", total)

The output of the above example is:

函数内是局部变量 :  30
函数外是全局变量 :  0

1. Global variables: Variables defined outside a function can be accessed throughout the entire file. Variables defined outside a function are visible to all functions, unless a local variable with the same name is defined inside the function.

Example

x = 10  # Global variable

def my_function():
    print(x)  # Can access global variable x

my_function()  # Outputs 10

2. Local variables: Variables defined inside a function are only valid within the function and cannot be accessed outside. Local variables have higher priority than global variables, so if a local variable and a global variable have the same name, the local variable is used inside the function.

Example

def my_function():
    x = 5  # Local variable
    print(x)  # Access local variable x

my_function()  # Outputs 5
print(x)  # Error: NameError: name 'x' is not defined

The global and nonlocal Keywords

When an inner scope wants to modify a variable in an outer scope, the global and nonlocal keywords are needed.

The following example modifies the global variable num:

Example (Python 3.0+)

#!/usr/bin/python3 num = 1 def fun1(): global num # Need to declare using the global keyword print(num) num = 123 print(num) fun1() print(num)

The output of the above example is:

1
123
123

If you want to modify a variable in a nested scope (enclosing scope, the outer non-global scope), you need the nonlocal keyword, as in the following example:

Example (Python 3.0+)

#!/usr/bin/python3 def outer(): num = 10 def inner(): nonlocal num # Declare with the nonlocal keyword num = 100 print(num) inner() print(num) outer()

The output of the above example is:

100
100

There is also a special case. Suppose the following code is executed:

Example (Python 3.0+)

#!/usr/bin/python3 a = 10 def test(): a = a + 1 print(a) test()

When the above program is executed, the error message is as follows:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 5, in test
    a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

The error message is a local scope reference error, because a in the test function uses the local one, which is undefined and cannot be modified.

Modify a to be a global variable:

Example

#!/usr/bin/python3 a = 10 def test(): global a a = a + 1 print(a) test()

The execution output is:

11

It can also be passed through function parameters:

Example (Python 3.0+)

#!/usr/bin/python3 a = 10 def test(a): a = a + 1 print(a) test(a)

The execution output is:

11

Summary

  • Global variablesDefined outside a function, can be accessed throughout the entire file.
  • Local variablesDefined inside a function, can only be accessed within the function.
  • UseglobalYou can modify global variables inside a function.
  • UsenonlocalYou can modify variables of the outer function inside nested functions.
Other extensions