How to statically get TypeVar parameters from a Generic for use in static type checking?

我与影子孤独终老i 提交于 2021-02-08 10:40:36

问题


I have a class that inherits from typing.Generic and passes in one TypeVar as the parameter.

Later on in the code, I would like to:

  1. Statically (not at runtime) get the TypeVar parameter out from the class
  2. Alias it to another type variable
  3. Use that alias to type hint the return of a function

Is there some way in Python that I can make this happen?

The only piece I am missing is step 1, how to get the type parameter out of a type variable


My Use Case

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

I then import BaseDataClass and ChildDataClass into another module.

In that second module, is there some way to statically get the TFloat parameter from BaseDataClass, or the int parameter from ChildDataClass, and use it in mypy?

FYI: I am using Python 3.8.2.


回答1:


There isn't a way of "getting" out a type variable. You shouldn't think of a type variable as being like a chunk of data you can potentially extract somehow. Instead, think of it as a part of a definition.

I think based on your question, what you're really after is a way of writing a function that accepts some BaseDataClass[T] (or a subclass of this type) and returns whatever T is.

If so, create a function that matches the definition of whatever you want to accept. But instead of specifying that the inner type must be something specific, capture it using a generic instead.

In this case, we chose to match against anything of type BaseDataClass[T], where we keep T generic. And our return type will be whatever T happened to match up against.

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"

For more details and examples, see the mypy docs on generics.



来源:https://stackoverflow.com/questions/62354233/how-to-statically-get-typevar-parameters-from-a-generic-for-use-in-static-type-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!