You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python作用域规则疑问:两段嵌套函数代码为何运行结果不同?

为什么第一段Python代码正常运行,第二段却触发UnboundLocalError?

这个问题的核心在于Python处理变量作用域的一个关键规则——只要函数内部存在对变量的赋值操作,Python就会把这个变量标记为该函数的局部变量,不管赋值语句写在代码的哪个位置。咱们分别拆解两段代码来理解:

第一段代码:正常运行的原因

先看这段能正常输出的代码:

name = "Sammy"
def greet():
    name = 'johny'
    def hello():
        print('hello ' + name)  # gets 'name' from the enclosing 'greet'
    hello()
greet()

运行后输出hello johny,完全符合预期。

这里的关键是:hello()函数里只引用了name,没有对它做任何赋值操作。Python会按照LEGB规则(局部作用域Local → 外层嵌套作用域Enclosing → 全局作用域Global → 内置作用域Built-in)逐层查找变量:

  • 首先在hello自己的局部作用域找name,找不到;
  • 接着去外层的greet函数作用域找,发现这里定义了name = 'johny',就直接用这个值;
  • 根本不会去全局作用域的name = "Sammy"那里找,所以输出结果没问题。

第二段代码:报错的根源

再看这段触发错误的代码:

x = 50
def func1():
    x = 20
    def func2():
        print("x is ", x)  # Generates error here
        x = 2
        print("Changed the local x to ",x)
    func2()
func1()
print("x is still ",x)

运行时抛出UnboundLocalError: local variable 'x' referenced before assignment。

问题出在func2()内部的x = 2这行代码:Python在编译func2的时候,只要看到函数内部有对x的赋值,就会立刻把x标记为func2的局部变量。

所以当func2执行到print("x is ", x)时,它会直接去func2自己的局部作用域找x,但此时x还没被赋值(赋值语句在后面),自然就会抛出“局部变量在赋值前被引用”的错误。哪怕外层的func1里有x=20、全局有x=50,Python也不会再去这些外层作用域查找x了——因为它已经认定x是func2的局部变量。

如何修复第二段代码?

如果想让func2引用并修改外层func1里的x,可以用nonlocal关键字明确声明x来自外层嵌套作用域:

x = 50
def func1():
    x = 20
    def func2():
        nonlocal x  # 告诉Python:x不是我自己的局部变量,去外层嵌套作用域找
        print("x is ", x)
        x = 2
        print("Changed the local x to ",x)
    func2()
func1()
print("x is still ",x)

修改后运行会输出:

x is  20
Changed the local x to  2
x is still  50

如果你的需求是引用全局的x,那就换成global关键字,但显然这里的场景更适合用nonlocal。


内容的提问来源于stack exchange,提问作者Aswin P J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:56:28