获取泛型替代类型

Get generic substituted type

我有这样的 class:

from typing import Generic, TypeVar
from pydantic import BaseModel

T = TypeVar("T", bound=BaseModel)

class A(Generic[T]):
    def some_method(self) -> T:
        ... # some data processing
        return T.from_orm(some_data_model)

# in tests package:
class Model(BaseModel): ...
A[Model].some_method()
assert Model.from_orm.called_once

但它不起作用,因为 T 不是 不是 真实类型(BaseModel),而只有 TypeVar 绑定到 BaseModel.

所以问题是:如何获得 真实(替代)类型 T?

重要提示:

it doesn't matter for me what the type the method is(classmethod, method of object instance or staticmethod)

my python version is 3.8

答案对我没有帮助:

我试过这个:

from typing import ..., get_args
#   ...
    def some_method(self) -> T:
        ...
        return get_args(type(self))[0].from_orm(some_data_model)

这个:

from typing import ..., get_args
#   ...
    @classmethod
    def some_method(cls) -> T:
        ...
        return get_args(cls)[0].from_orm(some_data_model)

还有这个:

from typing import ..., get_args
#   ...
    @classmethod
    def some_method(cls) -> T:
        ...
        return get_args(A)[0].from_orm(some_data_model)

我是这样调用的(如果是class/static方法):

A[Model].some_method()

如果是实例方法:

A[Model]().some_method()

所有这些(不调用 from_orm 并获取索引 0)只是 returns 空元组,整个方法以 IndexError 结束(这是完全正确的)。

在评论中@alex_noname 发布了一个 link 到另一个这样的问题。

在我的例子中,答案是使用 self 对象的 __orig_class__ 属性:

from typing import Generic, TypeVar, get_args
from pydantic import BaseModel

T = TypeVar("T", bound=BaseModel)

class A(Generic[T]):
    def some_method(self) -> T:
        ... # some data processing
        return get_args(self.__orig_class__)[0].from_orm(some_data_model)

更多信息请参考