问题
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:
- Statically (not at runtime) get the
TypeVarparameter out from the class - Alias it to another type variable
- Use that alias to type hint the
returnof 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