如何为Python带Generic类型的dataclass添加类型注解?
问题根源
运行时Python会解析字段注解的表达式:当你写type: Optional[type[T]]时,这里的type会被识别为内置的type()函数,而函数是不可下标对象,执行[T]操作就会抛出TypeError。但mypy作为静态检查工具,会把注解里的type当作类型构造器处理,因此不会报错。
解决方案
方案1:使用typing.Type替代内置type
typing.Type是专门为类型注解设计的泛型类型,运行时是合法的可下标对象,能同时兼容mypy和pytest:
from dataclasses import dataclass, KW_ONLY from typing import Optional, TypeVar, Generic, Type # 新增Type导入 T = TypeVar("T") @dataclass class CommandLineArgument(Generic[T]): name_or_flags: str | tuple[str] _: KW_ONLY metavar: Optional[str] = None type: Optional[Type[T]] = None # 用Type[T]替代type[T] default: Optional[T] = None
方案2:使用字符串类型注解
如果不想新增Type导入,可以将注解写成字符串形式,运行时Python不会解析该表达式,仅作为字符串存储,mypy仍能正确解析:
from dataclasses import dataclass, KW_ONLY from typing import Optional, TypeVar, Generic T = TypeVar("T") @dataclass class CommandLineArgument(Generic[T]): name_or_flags: str | tuple[str] _: KW_ONLY metavar: Optional[str] = None type: "Optional[type[T]]" = None # 字符串形式的注解 default: Optional[T] = None
方案3:重命名字段(可选)
若允许修改字段名,直接避开与内置type的冲突:
from dataclasses import dataclass, KW_ONLY from typing import Optional, TypeVar, Generic T = TypeVar("T") @dataclass class CommandLineArgument(Generic[T]): name_or_flags: str | tuple[str] _: KW_ONLY metavar: Optional[str] = None arg_type: Optional[type[T]] = None # 重命名为arg_type default: Optional[T] = None
其中方案1是最推荐的,既保留了与ArgumentParser.add_argument一致的参数命名习惯,又能在静态检查和运行时都正常工作。
内容的提问来源于stack exchange,提问作者palao
相关产品推荐
相关产品推荐

