You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在实例化泛型类时复用当前类的泛型类型?

如何在泛型类中复用自身泛型类型实例化另一个泛型类?

当泛型类B被具体类型(如str)实例化后,要在B的方法里复用这个具体类型来实例化泛型类A,现有两种尝试都存在问题:

  • 直接写A[T]()会运行报错:object.__new__(X): X is not a type object (TypeVar),原因是类型变量T仅属于静态注解,运行时会被擦除,不是实际的类型对象
  • 通过self.__orig_class__.__args__[0]获取具体类型后实例化A[t](),虽然能正常运行,但会触发mypy的Variable "t" is not valid as a type错误,因为静态检查无法识别动态获取的类型变量

核心问题分析

Python的泛型类型变量(TypeVar)是为静态类型检查设计的,运行时会被擦除,所以直接用A[T]()无法得到有效类型;而__orig_class__是PEP 560引入的运行时属性,用于获取实例化时的原始泛型类型,但mypy的静态检查逻辑无法处理这种动态类型,因此会抛出错误。


解决方案1:优化泛型类设计,显式传递类型对象

修改A类,让它在初始化时接收具体的类型对象,彻底避免依赖泛型参数的运行时信息,同时保证静态检查能正常通过:

from typing import Generic, TypeVar, Type, cast
from typing import get_args

T = TypeVar('T')

class A(Generic[T]):
    def __init__(self, t_type: Type[T]):
        self.t_type = t_type

    def get_t(self) -> T:
        # 直接用传入的类型创建实例(支持带构造参数的类型,可按需修改)
        return self.t_type()

class B(Generic[T]):
    def get_t(self) -> T:
        # 运行时获取B实例对应的具体类型参数
        orig_class = self.__orig_class__
        t_type = get_args(orig_class)[0]
        # 用cast告知mypy该类型为Type[T],通过静态检查
        t_type = cast(Type[T], t_type)
        # 实例化A时传入类型对象,无需依赖泛型参数语法
        a = A(t_type)
        return a.get_t()

if __name__ == '__main__':
    a = A[str](str)
    obj: str = a.get_t()
    print(type(obj))  # 输出:<class 'str'>

    b = B[str]()
    obj: str = b.get_t()
    print(type(obj))  # 输出:<class 'str'>

这种方案逻辑清晰,同时兼容运行时和静态检查,是更推荐的实现方式。


解决方案2:保留原泛型参数语法,兼容mypy检查

如果希望保留A类的原有设计,仅修改B类,可以通过cast和# type: ignore来绕过mypy的静态检查限制:

from typing import Generic, TypeVar, Type, cast
from typing import get_args

T = TypeVar('T')

class A(Generic[T]):
    def get_t(self) -> T:
        t = self.__orig_class__.__args__[0]
        obj = t.__new__(t)
        obj.__init__()
        return obj

class B(Generic[T]):
    def get_t(self) -> T:
        orig_class = self.__orig_class__
        t_type = get_args(orig_class)[0]
        t_type = cast(Type[T], t_type)
        # 用type: ignore忽略mypy对动态类型参数的检查
        a = A[t_type]()  # type: ignore[valid-type]
        return a.get_t()

if __name__ == '__main__':
    a = A[str]()
    obj: str = a.get_t()
    print(type(obj))  # 输出:<class 'str'>

    b = B[str]()
    obj: str = b.get_t()
    print(type(obj))  # 输出:<class 'str'>

这里用get_args替代直接索引__args__,代码更健壮;cast辅助mypy识别类型,# type: ignore跳过静态检查无法覆盖的动态类型部分。


注意事项

  • __orig_class__仅存在于泛型类的实例上,如果是继承泛型类的子类,可能需要额外处理类型参数的传递
  • 若目标类型需要构造参数,需在get_t方法中补充对应的初始化逻辑(比如传入__init__所需的参数)

内容的提问来源于stack exchange,提问作者Jeppe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 19:35:35