在Python中,作用域(Scope)是变量、函数和类在程序中的可见区域。Python主要有四种作用域:
-
局部作用域(Local Scope)
- 局部作用域是函数或方法内部定义变量的作用域。
- 变量在函数或方法内部声明,并且只能在函数或方法内部访问。
- 示例:
def my_function(): local_var = 20 # 局部作用域中的变量 print(local_var) my_function() # 输出: 20 # print(local_var) # 报错,因为local_var在函数外部不可见
-
嵌套作用域(Enclosing Scope 或 Nonlocal Scope)
- 嵌套作用域是指在一个函数内部定义的另一个函数的作用域。
- 内部函数可以访问外部函数的变量,但外部函数不能访问内部函数的变量。
- Python 3 引入了
nonlocal
关键字,允许内部函数修改外部函数的变量。 - 示例:
def outer_function(): outer_var = 30 # 外部函数的变量 def inner_function(): nonlocal outer_var # 声明outer_var为嵌套作用域中的变量 outer_var = 40 # 修改外部函数的变量 print(outer_var) inner_function() print(outer_var) # 输出: 40 outer_function()
-
全局作用域(Global Scope)
-
全局作用域是在模块级别定义的变量的作用域。
-
在模块顶层定义的变量和函数都位于全局作用域。
-
示例:
global_var = 10 # 全局作用域中的变量 def my_function(): print(global_var) # 在函数中访问全局作用域中的变量 my_function() # 输出: 10
-
在函数内部,可以使用
global
关键字来声明一个变量是全局的。
-
-
内置作用域(Built-in Scope)
- 内置作用域是Python解释器在启动时创建的,包含了Python内置的函数和异常。
- 这个作用域对于所有模块都是全局的,并且你不能创建新的内置变量或函数。
- 示例:
print(len([1, 2, 3])) # 使用内置作用域中的函数len()
5.其它
(1)作用域对象的本质:
- 在Python中,作用域对象是一个存储变量和函数名称与其对应值的字典。它用于存储当前作用域中的变量和函数。
(2)变量的查找顺序(LEGB原则):
- 局部(Local) -> 嵌套(Enclosing) -> 全局(Global) -> 内置(Built-in)
- Local(局部):首先在当前函数或方法的局部作用域中查找。
- Enclosing(嵌套):如果变量在局部作用域中未找到,并且该函数是在另一个函数内部定义的(即嵌套函数),那么搜索会继续在外部函数的局部作用域中查找。
- Global(全局):如果变量在嵌套作用域中仍未找到,那么搜索会继续在全局作用域中查找,即模块的顶层。
- Built-in(内置):最后,如果变量在全局作用域中仍未找到,那么搜索会在内置作用域中查找,即Python解释器启动时创建的内置函数和异常。
以下是一个展示LEGB原则的示例:
# 内置作用域(Built-in Scope)中的变量(例如len)
print(len([1, 2, 3])) # 使用内置作用域中的len函数
# 全局作用域(Global Scope)中的变量
global_var = "I'm global"
def outer_function():
# 嵌套作用域(Enclosing Scope)中的变量
enclosing_var = "I'm enclosing"
def inner_function():
# 局部作用域(Local Scope)中的变量
local_var = "I'm local"
# 试图访问四个作用域中的变量
print(local_var) # 局部作用域
print(enclosing_var) # 嵌套作用域
print(global_var) # 全局作用域
print(len([1, 2, 3])) # 内置作用域
# 试图访问不存在的变量(会按照LEGB原则进行搜索)
# 如果在当前作用域未找到,将会依次向上一级作用域搜索
try:
print(nonexistent_var) # 将会引发NameError
except NameError as e:
print(f"NameError: {e}")
inner_function()
outer_function()
"""
`inner_function`中的`print`语句会首先尝试访问局部作用域中的变量`local_var`,
然后是嵌套作用域中的`enclosing_var`,接着是全局作用域中的`global_var`,
最后是内置作用域中的`len`函数。如果试图访问一个不存在的变量(如`nonexistent_var`),
Python会按照LEGB原则进行搜索,直到找到为止。如果在所有作用域中都未找到,
则会引发`NameError`异常。
"""