from typing import Generic, get_args
_T = TypeVar("_T")
class SomeClass(Generic[_T]):
def __init__(self, x: _T):
self.x = x
def add(self, y: _T):
self.x += y
c = SomeClass[int](5)
c.add(2)
print(c.x)This works fine with static type checking. However, if you want to resolve T at runtime, this won't work. For example, if you want to define some common methods for the repositories in your application:
class BaseRepository(Generic[_T]):
def count(self):
with Session(...) as session:
return session.query(_T).count()
class UserRepository(BaseRepository[UserModel]):
pass
user_repo = UserRepository()
user_repo.count() # WON'T WORKThis won't work, since at runtime T has no value you can access. You have to use some dark magic™ in order to resolve T at runtime.
class BaseRepository(Generic[_T]):
_my_T = None
def __init_subclass__(cls):
cls._my_T = typing.get_args(cls.__orig_bases__[0])[0]
# ^~~~~ subclass's class variable
# __init_subclass__ runs everytime a subclass is DEFINED
def count(self):
with Session(...) as session:
return session.query(self._my_T).count()
# ^~~~~ subclass's class variable
class UserRepository(BaseRepository[UserModel]):
pass
user_repo = UserRepository()
user_repo.count()