nameerror在运行时才报错,因为python是解释执行、动态作用域语言,变量仅在执行到定义语句时才进入作用域;未执行定义就引用即触发错误。

为什么NameError: name 'xxx' is not defined总在运行时才报?
因为 Python 是解释执行、动态作用域的语言,变量只有在被实际执行到定义语句时才进入当前作用域。没运行到 xxx = 10 这行,就去用 xxx,立刻崩。
常见触发场景:
- 变量定义写在了
if或try块里,但实际分支没走过去 - 函数内部用了外部变量,但该变量在函数调用之后才定义
- 拼写错误:定义的是
user_name,却写了username - 在类方法里漏写了
self.,比如把self.data写成data
检查变量是否在正确作用域中声明
Python 的 LEGB 规则(Local → Enclosing → Global → Built-in)决定了查找顺序。你看到的 xxx 不一定来自你“以为”的地方。
实操建议:
- 用
print(locals())和print(globals().keys())快速确认当前作用域有哪些变量 - 如果在函数内报错,先检查是不是忘了
global xxx或nonlocal xxx声明(尤其嵌套函数修改外层变量时) - 交互式环境(如 IPython)中,变量可能来自前一次运行残留;重启 kernel 再试,排除污染
- 模块导入后,变量属于模块命名空间,不能直接用——比如
import math后要写math.pi,不能只写pi
定义顺序问题:不是所有代码都从上到下“可见”
函数和类的定义本身是可跳过的(它们只是创建对象并绑定名字),但其中的代码体不会提前执行。所以下面这段会报错:
func()
def func():
print("ok")
同理,条件块里的定义不保证执行:
if False:
x = 100
print(x) # NameError
解决办法:
- 把变量初始化提到最外层,哪怕设为
None:x = None,再在条件中赋值 - 用
try/except NameError捕获并提供默认逻辑(慎用,掩盖真实问题) - 避免在函数调用前依赖尚未执行的赋值语句——把调用移到定义之后,或重构为函数入口统一调度
容易被忽略的隐式作用域陷阱
有些语法看着像“只是计算”,其实会创建新作用域,导致变量不可见:
-
list comprehension在 Python 3 中有独立局部作用域:[x for x in range(3)]结束后,x不会泄露到外层 -
lambda捕获的是变量名,不是值;循环中反复定义 lambda 时,容易全指向最后一个i——这不是NameError,但常和它一起排查 - Jupyter Notebook 单元格执行顺序混乱:第二单元格用了第一单元格定义的变量,但你没运行第一单元格
- 使用
exec()或eval()时,变量默认在局部作用域里,除非显式传入globals和locals字典
真正在意变量生命周期的时候,别靠猜——加一行 print('defined:', 'xxx' in locals()),比翻文档快得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











