Python变量作用域LEGB规则疑问:为何找不到pass_a中的变量b?
理解Python的静态作用域(纠正LEGB规则的常见误解)
嘿,这个问题是对Python作用域规则的典型误解——咱们先把你的代码清晰列出来,再一步步拆解问题所在:
你的代码及报错
def fun(): print b def pass_a(b): fun() pass_a(2)
执行后触发报错:
NameError: global name 'b' is not defined
问题出在哪?你对LEGB的理解差了关键一点
你提到的LEGB(Local→Enclosing→Global→Built-in)查找顺序是对的,但这里的核心误区是:Python采用的是「词法作用域(静态作用域)」,不是动态作用域。
简单说,函数的作用域是在定义的时候确定的,而不是在调用的时候。咱们对应你的例子来看:
fun函数是直接定义在全局作用域中的,它的「Enclosing(嵌套)作用域」就是全局作用域,和pass_a函数没有嵌套关系- 当你在
pass_a里调用fun时,fun并不会去pass_a的局部作用域里找b——因为它的作用域在定义时就已经绑定到了全局,不会随着调用位置变化而改变
怎么修改才能让代码符合你的预期?
如果想让fun能访问pass_a中的b,需要把fun嵌套定义在pass_a内部,这样它的Enclosing作用域就会绑定到pass_a的局部作用域:
def pass_a(b): def fun(): print b fun() pass_a(2) # 此时会正常输出2
这时候调用fun时,LEGB查找就会先在fun的Local作用域找b(找不到),然后去Enclosing作用域(也就是pass_a的局部作用域)找到b,顺利执行。
再划个重点
LEGB规则里的「Enclosing作用域」,指的是函数定义阶段包裹它的外层函数作用域,而不是函数调用阶段所在的栈帧作用域。Python的作用域绑定是静态的,这是它和部分动态作用域语言的核心区别。
内容的提问来源于stack exchange,提问作者Lisa
相关产品推荐
相关产品推荐

