Skip to content

解决 Python 中的 TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'

问题描述

当在 Python 3.9 中尝试使用联合类型语法 |(例如 str | None)时,会遇到以下错误:

python
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'

这个报错出现在如下的类定义中:

python
from dataclasses import dataclass

@dataclass
class InventoryItem:
    """库存物品追踪类"""
    name: str | None = None  # ❌ 在 Python 3.9 中会引发错误
    unit_price: float
    quantity_on_hand: int = 0

错误原因

报错的根本原因在于:

  • | 语法用于联合类型 (Union Types) 是 Python 3.10 才引入的新特性
  • Python 3.9 及更低版本不具备理解 type1 | type2 的能力
  • NoneType 是特殊类型,不支持与常规类型直接进行 | 运算

解决方案

方法 1:使用 typing.Optional (首选方案)

typing.Optional 是表示"某种类型或 None"的标准解决方案,兼容 Python 3.5+。

python
from typing import Optional
from dataclasses import dataclass

@dataclass
class InventoryItem:
    """库存物品追踪类"""
    name: Optional[str] = None  # ✅ Python 3.9 中安全的方式
    unit_price: float
    quantity_on_hand: int = 0

重要提示

确保数据类中 字段顺序正确:没有默认值的字段必须声明在带有默认值的字段前面。

方法 2:使用 typing.Union (多类型场景)

当需要联合多于两种类型时,使用 typing.Union

python
from typing import Union

# 接受 str, int, float 三种类型
value: Union[str, int, float] = 42

# 接受 str 或 None 类型
text: Union[str, None] = None

Python 3.10+ 的正确写法

如果环境升级到 Python 3.10+,可以恢复使用简化的 | 语法:

python
@dataclass
class InventoryItem:
    """库存物品追踪类"""
    name: str | None = None  # ✅ Python 3.10+ 中安全可用
    unit_price: float
    quantity_on_hand: int = 0

注意事项

  1. Optional[str]Union[str, None] 在功能上完全等价
  2. Optional[...] 更简洁,是表示可空值的惯用写法
  3. 避免尝试用 or 替代,如 str or None,这会导致不同语义的错误

完整修正代码

综合考虑字段顺序和类型注解兼容性的最终方案:

python
from typing import Optional
from dataclasses import dataclass

@dataclass
class InventoryItem:
    """库存物品追踪类"""
    unit_price: float  # 🚫 无默认值字段在前
    name: Optional[str] = None  # ✅ 使用 Optional 声明可空类型
    quantity_on_hand: int = 0  # 有默认值字段在后

关键点总结

问题场景Python 3.9 解决方案Python 3.10+ 解决方案
strNoneOptional[str]str | None
多种类型联合Union[Type1, Type2, ...]Type1 | Type2 | ...
类字段顺序问题无默认值的字段必须在前面无默认值的字段必须在前面

遇到类似的 TypeError 时,首先检查 Python 版本,并根据运行环境选择恰当的联合类型语法。遵循这些注意事项将帮助你避免这种类型错误,并能写出在不同 Python 版本间兼容的类型注解代码。