深入理解Python函数作用域与LEGB查找规则
本文详细解析Python中函数作用域的查找机制,重点介绍LEGB(Local, Enclosing, Global, Built-in)规则。通过代码示例说明局部变量、嵌套函数及全局变量的访问顺序,并解释名称空间的概念及其在变量绑定中的作用,帮助开发者准确理解变量可见性与生命周期。
在Python语言中,函数定义即创建了一个独立的作用域。
name = 'xiaoyafei'
def change_name():
name = '肖亚飞'
print('在change_name里的name:',name)
change_name() # 调用函数
print("在外面的name:",name)
程序执行后的输出结果如下所示:
在change_name里的name: 肖亚飞 在外面的name: xiaoyafei
接下来,我们探讨在嵌套函数结构中变量是如何被查找的。
age = 15
def func():
print('第一层age:',age) # 第一层age: 15
def func2():
age = 73
print("func2中的age:",age) # func2中的age: 73
def func3():
age = 84
print("func3中的age:",age) # func3中的age: 84
func3() # 调用func3函数
func2() # 调用func2函数
func()
上述嵌套函数的例子清晰地展示了“一个函数对应一个作用域”的原则。现在,我们对代码进行微调,观察变化情况。
age = 15
def func():
print('第一层age:',age) # 第一层age: 15
def func2():
print("func2中的age:",age) # func2中的age: 15 # 看到没有,如果当前作用域里没有age变量,那么它就会往上找
def func3():
age = 84
print("func3中的age:",age) # func3中的age: 84
func3() # 调用func3函数
func2() # 调用func2函数
func()
有人可能会质疑,这不过是在讲解局部变量与全局变量的区别。那么问题来了:在上面的嵌套函数中,func2内部并未定义age变量,它是如何定位到全局变量age = 15的呢?
为了解答这一疑问,我们需要明确变量作用域的查找顺序。
变量作用域遵循LEGB规则。
- L: locals(局部作用域),即函数内部的名称空间,包含局部变量和形式参数。
- E: enclosing(嵌套作用域),指外部嵌套函数的名称空间,即相邻的上一层函数。例如,若func2中未找到age变量,则会向func函数中查找。
- G: globals(全局作用域),即全局变量所在的名称空间。
- B: builtins(内置作用域),即内置模块的名称空间。
在深入探讨之前,我们先厘清“名称空间”的概念。
名称空间(Name Space),顾名思义,是存储名称的地方。它存储的是什么样的名称呢?举例来说,执行x = 1时,数值1存储在内存中,而变量名x存储在哪里?名称空间正是存放变量名x与数值1之间绑定关系的位置。
>>> x = 1 >>> id(1) 1576430608
名称空间主要包含以下三种类型:
- locals:函数内的名称空间,涵盖局部变量和形参。
- globals:全局变量,即函数定义所在模块的名称空间。
- builtins:内置模块的名称空间。
不同变量的作用域差异,正是由变量所在的名称空间所决定的。
作用域即变量的有效范围。
- 全局范围:全局存活,全局有效。
- 局部范围:临时存在,仅局部有效。
我们通过具体示例来观察这一机制。
level = 'L0'
n = 22
def func():
level = 'L1'
n = 33
print(locals()) # {'n': 33, 'level': 'L1'} 在之前说过在python中,一个函数就是一个作用域,这就很完美的体现了
def outer():
n = 44
level = 'L2'
print(locals(),n) # {'level': 'L2', 'n': 44} 44
def inner():
level = 'L3'
print(locals(),n) # {'level': 'L3', 'n': 44} 44
inner()
outer()
func()
查找遵循 L --> E --> G --> B 的顺序,即:首先在局部作用域查找,若未找到则向局部外部的局部(如闭包)查找,再未找到则去全局作用域查找,最后去内置函数中查找。
总结
以上是对Python函数作用域的详细介绍,希望能为读者提供帮助。如有任何疑问,欢迎留言,小编会及时回复。感谢大家对本站的支持!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













