I have the following setup:
T = TypeVar("T")
@dataclass
class Type(Generic[T]):
name: str
data: T
@dataclass
class Aspect:
name: str
from: Type[str]
to: Type[int]
func: Callable[[Type[str]], Type[int]]
This works great, but I've tied my Callable to str and int, and I would want something even more generic like being able to define func as something like:
func: Callable[[Type[A]], Type[B]]
where A and B can be whatever, so I can define and send a func like (a: Type[str]) -> Type[int]:...
or (a: Type[float]) -> Type[str]:...
or whatever
Right now I can have a function:
def func1(a: Type[str]) -> Type[int]:
return Type("func1", 1)
which I can use to create an Aspect Aspect("asp1", type1, type2, func1)
But I can't create an Aspect in the same way with a function like:
def func2(a: Type[int]) -> Type[str]:
return Type("func2", "2")
and then call Aspect("asp1", type1, type2, func2)
I've tried creating different TypeVars to use in the callable, but it doesn't work, mypy says they are unbound, I've also tried to work around this with ABC but to no success, is there any way to express this?
CodePudding user response:
Generics allow you to bind a generic type T
, A
, or B
to a concrete type within a class or function. In your case you want every instance of A
and B
represent the same type across the entire class, therefore you must bind
A
and B
inside a class by extending Generic[A, B]
.
T = TypeVar('T')
A = TypeVar('A')
B = TypeVar('B')
@dataclass
class MyType(Generic[T]):
name: str
data: T
@dataclass
class Aspect(Generic[A, B]):
name: str
from_: MyType[A]
to: MyType[B]
func: Callable[[MyType[A]], MyType[B]]
(changed Type
to MyType
to avoid confusion with typing.Type
)
It essentially tells python: "Let's define A
and B
to mean the same thing across the class"