介绍
在 Python 中,作用域(Scope) 和 命名空间(Namespace) 是管理变量访问和存储的核心概念。理解它们对于编写高效、可维护的代码非常重要。
作用域
作用域 指的是 变量的可见范围,决定了变量在程序中的哪些部分可以被访问。
Python 采用 LEGB 规则 确定变量的作用域:
- L(Local,局部作用域):函数内部定义的变量,仅在函数内部有效。
- E(Enclosing,嵌套作用域):嵌套函数的外层函数作用域(非全局)。
- G(Global,全局作用域):当前 Python 文件(模块)内的全局变量。
- B(Built-in,内置作用域):Python 内置的变量,比如 len()、print()。
LEGB 规则的搜索顺序:
- Local(局部) → Enclosing(嵌套) → Global(全局) → Built-in(内置)
- 一旦找到匹配的变量,就不会继续向上搜索。
作用域示例
|
|
代码的输出是
|
|
命名空间
命名空间 是存储变量(名字 → 值 映射)的地方,每个变量名在 Python 里都会被存储在某个命名空间中。
局部命名空间
- 每个函数都会创建自己的局部命名空间,存储局部变量。
- 变量在函数执行完后会被销毁。
|
|
全局命名空间
- 存储模块级变量,即定义在函数之外的变量。
- 只要 Python 解释器运行,变量就存在。
|
|
内置命名空间
由 Python 解释器预定义的内置函数和对象,例如 print(), len(), list()。
|
|
命名空间生命周期
- 函数内部赋值的变量 会被认为是局部变量,不会影响外部变量。
- 要修改全局变量,需要使用 global 关键字。
- 要修改嵌套作用域变量,需要使用 nonlocal 关键字。
global 与 nonlocal 关键字
在 Python 中,默认情况下:
- 函数内部赋值的变量 会被认为是局部变量,不会影响外部变量。
- 要修改全局变量,需要使用 global 关键字。
- 要修改嵌套作用域变量,需要使用 nonlocal 关键字。
|
|
💡 不加 global,x 在 change_global() 内部是局部变量,不会影响外部变量。
|
|
💡 不加 nonlocal,inner() 里的 x 只是局部变量,不会影响 outer() 里的 x。
作用域与命名空间的关系
- 作用域是变量的可见范围,而命名空间是变量的存储位置。
- 作用域决定了 Python 解释器在多个命名空间中如何查找变量。
- Python 按照 LEGB 规则 在不同的命名空间中搜索变量。
locals() 与 globals()
locals() 和 globals() 是 Python 内置的两个函数,它们分别用于访问 局部命名空间(Local Namespace) 和 全局命名空间(Global Namespace)。
注意:locals()函数在全局作用域调用,返回的就是全局命名空间的字典