Issue
I want to annotate a generic function which takes as arguments another function and its parameters.
def forward(func, **kwargs):
func(**kwargs)
So, if I have a function which takes two integers:
def sum_int(a: int, b: int):
...
in my editor I want help if I pass the wrong object types:
forward(sum_int, 1.5, 2.6) # want type checker to complain about using floats instead of integers
How can I annotate forward
? Something like:
def forward(func: Callable[rest, ret], **kwargs: rest] -> ret:
...
So, the first argument to forward
is func
and the rest
are the keyword arguments. The return is ret
. But rest
and ret
are also the keyword arguments and return type for func
.
I used to do generics years (decades!) ago in C++, and there were tricks for capturing and unpacking various types, but I don't know whether we have to jump through those kind of hoops with Python, or whether it's even possible.
I don't really know what to search for, and didn't turn up anything anywhere near helpful.
Thanks!
Solution
You can use typing.ParamSpec
to associate the arguments expected by func
with the arguments expected by forward
, though you do apparently need to use both positional and keyword arguments in the definition of forward
:
RV = TypeVar('RV')
P = ParamSpec('P')
def forward(func: Callable[P, RV], *args: P.args, **kwargs: P.kwargs) -> RV:
...
def foo(*, a: int, b: int) -> str:
...
forward(foo, a=3, b=5) # OK
forward(foo, 3, 5) # Not OK, too many positional arguments for foo
Answered By - chepner
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.