def calc(price: float) -> float:
    if not isinstance(price, (int, float)):
        raise TypeError('price must be number')
    return price * 1.1

函数标着 price: float,传入字符串照样执行,直到乘法才抛 TypeError。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。

原因不复杂,注解在运行时只存进函数属性,解释器不做检查,类型不对要等运算碰到不支持的组合才暴露出来,写代码时看不出。

「Python 类型注解校验」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。

别只看报错的最后一行,往上看几行,真正的起因通常在上面。

处理上按这个顺序:在入口处用 isinstance 做一次显式校验;关键数据结构交给 pydantic 做运行期校验;提交前用 mypy 跑一遍,静态错误当场拦下。

改完只确认一件事:传字符串会立刻在入口抛 TypeError,报错里能看出是哪个字段。

作者 9823189