问题
I have a function which returns a function. I would like to find a proper type annotation. However, the returned function has *args
and *kwargs
. How is that annotated within Callable[[Parameters???], ReturnType]
?
Example:
from typing import Callable
import io
import pandas as pd
def get_conversion_function(file_type: str) -> Callable[[io.BytesIO, TODO], pd.DataFrame]:
def to_csv(bytes_, *args, **kwargs):
return pd.read_csv(bytes_, **kwargs)
if file_type == "csv":
return to_csv
回答1:
As I know, python's typing` does not allow do that straightforwardly as stated in the docs of typing.Callable:
There is no syntax to indicate optional or keyword arguments; such function types are rarely used as callback types. Callable[..., ReturnType] (literal ellipsis) can be used to type hint a callable taking any number of arguments and returning ReturnType.
But you could use mypy extensions like this:
from typing import Callable
from mypy_extensions import Arg, VarArg, KwArg
def foo(a: str, *args: int, **kwargs: float) -> str:
return 'Hello, {}'.format(a)
def bar() -> Callable[[Arg(str, 'a'), VarArg(int), KwArg(float)], str]:
return foo
回答2:
With the introduction of typing.Protocol
, MyPy (and other compliant type checkers) support the full call syntax natively via the __call__
special method.
MyPy: Callback Protocols
Protocols can be used to define flexible callback types that are hard (or even impossible) to express using the
Callable[...]
syntax, such as variadic, overloaded, and complex generic callbacks. (...)
Simply define a Protocol
whose __call__
method has the desired signature.
from typing import Protocol
class SomeCallable(Protocol):
def __call__(self, a: str, b: int, *args: float, kwargs: str) -> bytes: ...
def my_callable(a: str, b: int, *args: float, kwargs: str) -> bytes:
return b"Hello World"
def my_func(key: str) -> SomeCallable:
return my_callable
来源:https://stackoverflow.com/questions/62809562/how-do-i-annotate-a-callable-with-args-and-kwargs