3、名称错误(NameError):变量未定义、函数名拼写错误、作用域问题

名称错误,说白了就是 Python 找不到你写的那个名字。

你明明觉得变量已经定义好了,函数名也写对了,可解释器就是一脸茫然地抛出一个 NameError。我刚开始学建模时,几乎每天都要跟它打交道。后来发现,这类错误其实就三种情况:变量没定义、名字写错了、作用域搞混了。

3.1 变量未定义:最常见的翻车现场

先看一个典型例子:

# 错误示例
print(result)  # NameError: name 'result' is not defined
result = 42

为什么会这样?因为 Python 执行代码是顺序的。你还没给 result 赋值,就想打印它,它当然不认识。

我在项目中遇到过更隐蔽的情况:

# 条件分支里漏了定义
def process_data(value):
    if value > 0:
        result = value * 2
    # 如果 value <= 0,result 根本没被创建
    return result  # 可能报 NameError

嗯,这里要注意:条件分支、循环体、异常处理块里定义的变量,如果执行路径没走到,变量就不存在。

我的习惯:在函数开头就给关键变量一个默认值,比如 result = None。这样不管走哪条路,变量都活着。

3.2 函数名拼写错误:眼睛看花了

这种错误最气人。你盯着代码看了十分钟,愣是没发现哪里写错了。

# 定义时叫 calculate_average
def calculate_average(data):
    return sum(data) / len(data)

# 调用时写成了 calculate_avrage
avg = calculate_avrage(scores)  # NameError

我个人习惯用 IDE 的自动补全功能。打几个字母,让工具帮你补全函数名,基本能杜绝这种低级错误。

还有一种情况是大小写问题:

def LoadModel(path):
    # 加载模型
    pass

# 调用时写成了小写
load_model("model.obj")  # NameError

Python 是大小写敏感的。LoadModel 和 load_model 是两个完全不同的名字。

我曾经踩过的坑:在 Blender 插件开发中,一个函数名拼错了一个字母,排查了整整两个小时。后来我养成了一个习惯——写完调用后,按住 Ctrl 键点击函数名,如果能跳转到定义,说明名字写对了。

3.3 作用域问题:变量藏起来了

作用域,说白了就是变量的可见范围。你在函数里定义的变量,外面看不到;外面定义的变量,函数里可以读,但不能直接改。

看这个例子:

total = 0

def add_to_total(value):
    total = total + value  # UnboundLocalError
    return total

你可能会想:「total 不是全局变量吗?为什么报错?」

因为 Python 在函数内部给 total 赋值时,会把它当成局部变量。而局部变量 total 还没定义,你就想用它,自然报错。

正确的做法是:

total = 0

def add_to_total(value):
    global total
    total = total + value
    return total

或者更推荐的做法——用参数传递:

def add_to_total(total, value):
    return total + value
核心原则:函数内部尽量别直接修改全局变量。用参数传进去,用返回值带出来。这样代码更清晰,也不容易出作用域问题。

3.4 知识体系:名称错误全景图

下面这张图帮你理清 NameError 的三种根源和对应的解决思路:

NameError 名称错误全景图 NameError 名称错误 变量未定义 函数名拼写错误 作用域问题 常见场景 • 使用前未赋值 • 条件分支漏定义 • 变量名拼写不一致 常见场景 • 少写/多写字母 • 大小写不一致 • 下划线位置错误 常见场景 • 局部变量覆盖全局 • 嵌套函数闭包问题 • 模块导入未生效 解决方案 先赋值后使用 解决方案 用 IDE 自动补全 解决方案 用参数传递代替全局 核心原则:名字写对、变量活着、作用域清晰

3.5 避坑指南:我踩过的那些坑

错误类型 典型表现 排查方法
变量未定义 NameError: name 'xxx' is not defined 检查变量是否在之前被赋值,注意条件分支路径
函数名拼写错误 NameError: name 'xxx' is not defined 对比定义处的函数名,检查大小写和下划线
作用域问题 UnboundLocalError 或 NameError 确认变量是在局部还是全局,用 global 或参数传递
模块导入问题 NameError: name 'xxx' is not defined 检查 import 语句是否写对,模块是否已安装
我曾经遇到过一个特别隐蔽的坑:在 Maya 脚本里,我定义了一个函数叫 create_joint,但 Maya 自带的命令叫 cmds.joint。我写脚本时用了 create_joint 作为变量名,结果跟函数名冲突了。排查了半天才发现,原来是自己不小心把函数名当变量用了。

3.6 快速自查清单

遇到 NameError 时,按这个顺序检查:

  1. 拼写检查:名字里的每个字母、下划线、大小写都对吗?
  2. 定义顺序:变量在使用之前定义了吗?
  3. 执行路径:条件分支、循环、异常处理里有没有漏定义的路径?
  4. 作用域:变量是在当前作用域里定义的吗?函数内外搞混了没?
  5. 导入检查:如果是外部模块的函数,import 写了吗?模块名对吗?

嗯,其实 NameError 并不可怕。你想想看,它只是告诉你「这个名字我不认识」。你把它当成一个善意的提醒就好——帮你找到代码里的小漏洞。我个人觉得,能快速定位 NameError,是建模脚本入门的第一道坎。跨过去,后面的路就好走了。