As a toy example, consider a function that takes two types A
, B
and returns on object A(B)
. The standard example for this would be A = defaultdict
and B
e.g. int
. How can I annotate something like this? The closest I got is
from collections import defaultdict
from typing import TypeVar, Type, Protocol
Val = TypeVar('Val')
class InitableMapping(Protocol[Val]):
"""
A Protocol that enforces a MutableMapping with a special __init__
"""
def __init__(self, value_type: Type[Val]):
...
def __getitem__(self, item: int) -> Val:
...
def __setitem__(self, key: int, value: Val) -> None:
...
# more methods
M = TypeVar('M', bound=InitableMapping)
def build_mapping(mapping_type: Type[M], value_type: Type[Val]) -> InitableMapping[Val]:
return mapping_type(value_type)
foo = build_mapping(defaultdict, int)
print(foo.default_factory) # "InitableMapping[int]" has no attribute "default_factory"
where I put the MyPy output in the comments.
Obviously, the return annotation InitableMapping[Val]
is too broad, but M[int, Val]
can't work.
Would be glad for any help on this :) In fact even some keywords on what to look for would be great - I had a hard time coming up with a descriptive question title …
Update: A more realistic example might be something like
class MyClass(Generic[M, Val]):
def __init__(self, load: Callable[[], M[int, Val]]) -> None:
self.data = load()