为何参数化泛型会丢失__doc__属性?
泛型参数化后文档字符串丢失的原因与解决方法
问题本质
当你给泛型类传入类型参数(如Test[int])时,Python会动态生成一个泛型别名类(GenericAlias)——它不是原泛型类的实例,而是一个独立的类对象。这个动态生成的类默认不会继承原类的__doc__属性,这就是文档字符串丢失的核心原因。
你可以通过类型验证直观确认:
print(type(Test)) # <class 'type'>,原类是标准类对象 print(type(Test[int])) # <class 'typing._GenericAlias'>(Python 3.8)或 <class 'types.GenericAlias'>(Python 3.9+),是动态生成的别名类
这是预期行为吗?
是的,这是Python泛型系统的原生设计。泛型别名主要服务于静态类型检查和类型注解场景,运行时它的属性继承逻辑并不完整,__doc__属于未被自动复制的属性之一。原泛型类和参数化后的别名类在运行时是两个完全不同的对象,因此后者不会自动携带前者的文档字符串。
针对FastAPI/Pydantic场景的解决思路
如果你需要在FastAPI生成OpenAPI规范时保留文档字符串,可以尝试以下方案:
1. 手动复制文档字符串
适合少量使用的场景,直接在参数化后赋值:
TestInt = Test[int] TestInt.__doc__ = Test.__doc__
2. 自定义泛基类自动保留文档字符串
通过重写__class_getitem__方法,在生成泛型别名时自动复制原类的__doc__:
from typing import TypeVar, Generic T = TypeVar("T") class DocGeneric(Generic[T]): @classmethod def __class_getitem__(cls, item): generic_alias = super().__class_getitem__(item) generic_alias.__doc__ = cls.__doc__ return generic_alias class Test(DocGeneric[T]): """My docstring""" assert Test[int].__doc__ == "My docstring" # 断言可通过
注意:不同Python版本的泛型别名实现可能有差异,需测试适配你的环境。
3. 利用Pydantic/FastAPI原生配置
如果使用Pydantic的GenericModel,可以通过model_config或字段描述补充文档,避免依赖类的__doc__。例如在FastAPI中直接给路径操作参数指定description,而非依赖类的文档字符串。
内容的提问来源于stack exchange,提问作者ts91
相关产品推荐
相关产品推荐

