如何从泛型中静态获取TypeVar参数以用于静态类型检查?

问题描述 投票:0回答:1

我有一个从typing.Generic继承并传入一个TypeVar作为参数的类。

稍后在代码中,我想:

  1. 通常(不是在运行时)从类中获取TypeVar参数
  2. 将其别名到另一个类型变量
  3. 使用该别名键入提示功能的return

Python中是否有某种方法可以实现这一目标?

我唯一缺少的是步骤1,如何从类型变量中获取类型参数


我的用例

from abc import ABC, abstractmethod
from typing import TypeVar, Generic


TFloat = TypeVar("TFloat", bound=float)


class BaseDataClass(Generic[TFloat], ABC):

    @property
    @abstractmethod
    def data(self) -> TFloat:
        """Get data."""


class ChildDataClass(BaseDataClass[int]):

    @property
    def data(self) -> int:
        return 1

然后我将BaseDataClassChildDataClass导入另一个模块。

在第二个模块中,是否有某种方法可以从TFloat中静态获取BaseDataClass参数,或从int中静态获取ChildDataClass参数,并在mypy中使用它?

FYI:我正在使用Python 3.8.2。

python generics mypy static-typing python-typing
1个回答
0
投票

没有一种“获取”类型变量的方法。您不应将类型变量视为可以以某种方式提取的大量数据。而是将其视为定义的一部分。

[我根据您的问题认为,您真正想要的是一种编写接受某些BaseDataClass[T](或此类型的子类)并返回T是什么的函数的方法。

如果是这样,请创建一个函数,该函数matches您要接受的定义。但是,与其指定内部类型必须是特定的,不如使用泛型来捕获它。

在这种情况下,我们选择与BaseDataClass[T]类型的任何内容匹配,在这里我们保持T泛型。我们的返回类型将是T碰巧匹配的任何类型。

from typing import TypeVar
from other_module import BaseDataClass, ChildDataClass

T = TypeVar('T', bound=float)

def extract(wrapper: BaseDataClass[T]) -> T:
    return wrapper.data


# BaseDataClass[FloatSubclass] exactly matches against BaseDataClass[T],
# and so T will be FloatSubclass in 'extract(x)' call.

class FloatSubclass(float): pass
x: BaseDataClass[FloatSubclass]
reveal_type(extract(x))  # Mypy displays "FloatSubclass"


# ChildDataClass doesn't exactly match BaseDataClass[T], but the child
# class *is* a subtype of BaseDataClass[int], which does match.

x: ChildDataClass
reveal_type(extract(x))  # Mypy displays "int"

有关更多详细信息和示例,请参见mypy docs on generics

© www.soinside.com 2019 - 2024. All rights reserved.