How can I specify one type for all of these callables:
a(str)
b(str, str)
c(str, str, str)
d(str, str, str, str
I found that I can specify Callable[..., None]
in general way but how to specify with details that all arguments will be str without doing ugly syntax Union[Callable[[str], None], Callable[[str, str], None, __more_like_this__]
. Is it other method to do it? Can I do it with use typing?
You could use a callback protocol to specify a function type with variadic string arguments:
from typing_extensions import Protocol
class Callback(Protocol):
def __call__(self, *args: str) -> None: ...
And use it like this:
def handler(cb: Callback) -> None:
cb('a', 'b', 'c')
def callback(*args: str) -> None:
pass
handler(callback)
Note that the callback has to take variadic arguments, eg. this won't work:
def callback(a: str, b: str) -> None:
pass
Protocols were added in Python 3.8 to the standard library typing module, so if you want to use them on Python 3.5-3.7, you will need to install the typing-extensions module from PyPI.
What you want is the union of 4 distinct types.
t1 = Union[
Callable[[str],Any],
Callable[[str,str],Any],
Callable[[str,str,str],Any],
Callable[[str,str,str,str],Any],
]
Constrast that with the type of function that can accept 1 to 4 arguments:
t2 = Callable[[str,Optional[str],Optional[str],Optional[str]],Any]
A function like
def foo(x: str, y:str):
does not belong to the second type above. If I say I need a function of type t2
, you don't know how many arguments I might try to pass. I could give you foo
, but then you might try to pass 3 arguments, or only 1, and get a TypeError
.
If you ask for a function of type t1
, it's OK for me to give you foo
. t1
does not promise that all values in t1
can more or less than exactly 3 arguments; it only includes values that do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With