【Python】作用域与命名空间

介绍

在 Python 中,作用域(Scope) 和 命名空间(Namespace) 是管理变量访问和存储的核心概念。理解它们对于编写高效、可维护的代码非常重要。

作用域

作用域 指的是 变量的可见范围,决定了变量在程序中的哪些部分可以被访问。

Python 采用 LEGB 规则 确定变量的作用域:

  • L(Local,局部作用域):函数内部定义的变量,仅在函数内部有效。
  • E(Enclosing,嵌套作用域):嵌套函数的外层函数作用域(非全局)。
  • G(Global,全局作用域):当前 Python 文件(模块)内的全局变量。
  • B(Built-in,内置作用域):Python 内置的变量,比如 len()、print()。

LEGB 规则的搜索顺序:

  1. Local(局部) → Enclosing(嵌套) → Global(全局) → Built-in(内置)
  2. 一旦找到匹配的变量,就不会继续向上搜索。

作用域示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

代码的输出是

1
2
3
4
After local assignment: test spam
After nonlocal assignment: nonlocal spam
After global assignment: nonlocal spam
In global scope: global spam

命名空间

命名空间 是存储变量(名字 → 值 映射)的地方,每个变量名在 Python 里都会被存储在某个命名空间中。

局部命名空间

  • 每个函数都会创建自己的局部命名空间,存储局部变量。
  • 变量在函数执行完后会被销毁。
1
2
3
4
def foo():
    x = 10  # x 在局部命名空间
    print(x)
foo()

全局命名空间

  • 存储模块级变量,即定义在函数之外的变量。
  • 只要 Python 解释器运行,变量就存在。
1
2
3
4
y = 20  # y 在全局命名空间
def bar():
    print(y)  # 访问全局变量
bar()

内置命名空间

由 Python 解释器预定义的内置函数和对象,例如 print(), len(), list()。

1
print(len([1, 2, 3]))  # 访问内置命名空间的 `len`

命名空间生命周期

  • 函数内部赋值的变量 会被认为是局部变量,不会影响外部变量。
  • 要修改全局变量,需要使用 global 关键字。
  • 要修改嵌套作用域变量,需要使用 nonlocal 关键字。

global 与 nonlocal 关键字

在 Python 中,默认情况下:

  • 函数内部赋值的变量 会被认为是局部变量,不会影响外部变量。
  • 要修改全局变量,需要使用 global 关键字。
  • 要修改嵌套作用域变量,需要使用 nonlocal 关键字。
1
2
3
4
5
6
7
8
x = 100  # 全局变量

def change_global():
    global x  # 声明使用全局变量
    x = 200   # 修改全局变量

change_global()
print(x)  # 输出 200

💡 不加 global,x 在 change_global() 内部是局部变量,不会影响外部变量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def outer():
    x = 10  # 外部(Enclosing 作用域)

    def inner():
        nonlocal x  # 声明 `x` 来自外部作用域
        x = 20  # 修改 `outer()` 里的 `x`

    inner()
    print(x)  # 输出 20

outer()

💡 不加 nonlocal,inner() 里的 x 只是局部变量,不会影响 outer() 里的 x。

作用域与命名空间的关系

  • 作用域是变量的可见范围,而命名空间是变量的存储位置。
  • 作用域决定了 Python 解释器在多个命名空间中如何查找变量。
  • Python 按照 LEGB 规则 在不同的命名空间中搜索变量。

locals() 与 globals()

locals() 和 globals() 是 Python 内置的两个函数,它们分别用于访问 局部命名空间(Local Namespace) 和 全局命名空间(Global Namespace)。

注意:locals()函数在全局作用域调用,返回的就是全局命名空间的字典

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计