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

Python命名空间学习遇错:变量spam被引用前未声明

为什么我的Python命名空间代码报错"variable referenced before assignment"?

嘿,我来帮你把这个问题掰扯明白~

首先,咱们先抓准报错的核心原因:你在scope_test()函数里第一次执行print("before local assignment:", spam)的时候,当前scope_test()的函数作用域里根本还没定义spam变量!

你可能以为do_local()里定义了spam就能在外层用,但其实:

  • do_local()里的spam = "local spam"是创建了一个仅属于do_local()自身的局部变量,它的作用范围只限于这个小函数内部,出了do_local()就彻底消失了,完全不会影响外层scope_test()作用域里的变量。

那怎么改呢?我们需要先在scope_test()的作用域里初始化spam变量,给后续操作打个基础。另外我再帮你理清楚nonlocal和global的实际效果,修改后的代码如下:

def scope_test():
    # 先在scope_test的作用域里初始化spam,解决未声明的问题
    spam = "initial spam"
    
    def do_local():
        spam = "local spam"  # 仅在do_local内部生效的局部变量
    def do_nonlocal():
        nonlocal spam  # 指向外层嵌套作用域(scope_test)的spam
        spam = "nonlocal spam"
    def do_global():
        global spam  # 指向全局作用域的spam
        spam = "global spam"
    
    print("初始值:", spam)
    do_local()
    print("调用do_local后(不影响外层):", spam)
    do_nonlocal()
    print("调用do_nonlocal后(修改外层):", spam)
    spam = "test spam"
    print("手动赋值后:", spam)
    do_global()
    print("调用do_global后(修改全局,不影响当前函数作用域):", spam)

scope_test()
# 打印全局作用域的spam,验证global的效果
print("全局作用域的spam:", spam)

运行这段代码的输出会是:

初始值: initial spam
调用do_local后(不影响外层): initial spam
调用do_nonlocal后(修改外层): nonlocal spam
手动赋值后: test spam
调用do_global后(修改全局,不影响当前函数作用域): test spam
全局作用域的spam: global spam

最后再给你梳理下几个赋值逻辑的区别:

  • 普通赋值(比如do_local()里的操作):创建当前函数的局部变量,和外层变量完全无关
  • nonlocal:修改紧邻的外层嵌套函数作用域里的变量(不能用来修改全局变量)
  • global:修改全局作用域里的变量,和当前函数作用域的变量相互独立

内容的提问来源于stack exchange,提问作者Mahesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:09:30