函数定义顺序与Referenced Before Assignment Error:两段代码差异解析
为什么两段Python代码执行结果不同?
代码片段对比
代码片段#1
def bar(): print("Hello world") baz() def baz(): print("Hello user") bar()
执行结果:正常输出
Hello world Hello user
代码片段#2
def bar(): print("Hello world") baz() def baz(): print("Hello User") bar()
执行结果:触发 Referenced Before Assignment Error 错误
核心原因解析
先明确两个关键规则:
- Python函数定义是运行时执行的:函数体内的代码只有在调用函数时才会逐行执行,函数定义本身只是创建一个函数对象,不会触发内部逻辑。
- Python变量查找优先级:在函数内部引用名字时,先在当前局部作用域查找;如果局部作用域存在该名字的赋值语句(哪怕赋值在引用之后),Python会直接认定这是局部变量,不会去全局/上层作用域查找;只有局部没找到且无赋值声明时,才会往上搜索。
两段代码的具体分析:
代码片段#1:
bar和baz都是全局作用域下的函数。定义bar时,只是把bar绑定为函数对象,里面的baz()代码并未执行。等调用bar()时,baz已经在全局作用域完成定义,Python能在全局找到baz,因此正常执行。代码片段#2:
baz是bar内部的嵌套函数,属于bar的局部作用域。调用bar()时,代码按顺序执行:- 先打印"Hello world",无问题;
- 执行
baz()时,Python优先在bar的局部作用域找baz。此时虽然baz的定义在后面,但def baz()本质是给局部作用域的baz赋值,Python检测到局部有这个赋值操作,直接认定baz是局部变量,不会去全局查找; - 但此时局部的baz还未被定义(
def baz()还没执行到),所以触发了「引用未赋值」的错误。
内容的提问来源于stack exchange,提问作者LateGameLank
相关产品推荐
相关产品推荐

