Reputation: 2398
Consider a function which wraps another function and puts the output into a singleton list:
def listify(func):
return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]
How would you type-hint this function in python3? This is my best attempt:
from typing import Callable, TypeVar
T = TypeVar('T')
def listify(func: Callable[..., T]) -> Callable[..., List[T]]:
return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]
But I'm not happy that the returned Callable
does not inherit the signature of the argument types of the input Callable
. Is there any way to make that happen without making assumptions on the number of arguments of func
?
Upvotes: 4
Views: 1686
Reputation: 1121524
With the release of Python 3.10, and, for older Python versions, the typing-extensions
package version 3.10.0 and up, you can use a ParamSpec()
construct.
A ParamSpec()
object acts just like a TypeVar()
object, but instead of acting as a placeholder for a single parameter, it models the combination of arguments that a callable accepts.
Use such an object here as the placeholder for the arguments:
from typing import Callable, List, TypeVar
try:
from typing import ParamSpec
except ImportError:
from typing_extensions import ParamSpec
P = ParamSpec("P")
T = TypeVar("T")
def listify(func: Callable[P, T]) -> Callable[P, List[T]]:
return lambda *kargs, **kwargs: [func(*kargs, **kwargs)]
If you are stuck with Python 3.4 or older, then you can't do what you want with type hinting, as type_extensions
3.10.0 doesn’t support that Python version any more and there is no other syntax to capture the arguments part in a TypeVar
generic. Callable
was originally kept simple because it was really only meant to denote callback functions.
Upvotes: 1