Using TypeVar and Generic, I can create classes with methods where types can be inferred , e.g.:
from typing import TypeVar, Generic
T = TypeVar('T')
class Box(Generic[T]):
def __init__(self, content: T) -> None:
self.content = content
Box(1) # OK, inferred type is Box[int]
Is it possible to infer types of a class member? Let's say I have different types of athletes' stats:
from abc import ABC
from typing import Generic, TypeVar, Type
class Stats(ABC):
pass
class BaseballStats(Stats):
@property
def batting_average(self) -> float:
return 0.314
class FootballStats(Stats):
@property
def yards(self) -> int:
return 314
And now I want to define an abstract class for an athlete:
S = TypeVar('S', bound=Stats)
class Athlete(ABC, Generic[S]):
_stats_type: Type[S]
@property
def stats(self) -> S:
return self._stats_type()
If I try to make a BaseballPlayer and have it infer the type by assigning to _stats_type, it won't:
class BaseballPlayer(Athlete):
_stats_type = BaseballStats
bo = BaseballPlayer()
# reveal_type(bo.stats) --> gives `Any`; type was not inferred
print(bo.stats.batting_average) # works.
If I specify the type of Athlete but don't assign _stats_type, it won't run.
class FootballPlayer(Athlete[FootballStats]):
pass
bo = FootballPlayer()
# reveal_type(bo.stats) --> gives `FootballStats` because I explcitly called it out
print(bo.stats.yards) # AttributeError: 'FootballPlayer' object has no attribute '_stats_type'
Is there an alternative that doesn't require that I put the type of statistics in two places? I.e., can I avoid doing this?
class FootballPlayer(Athlete[FootballStats]):
_stats_type = FootballStats