我该如何使用*args和**kwargs注释可调用对象?

22

我有一个返回函数的函数。我希望找到一个合适的类型注释。然而,返回的函数有*args*kwargs。在Callable[[Parameters???], ReturnType]中如何注释?

例:

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
2个回答

28

引入了typing.Protocol,通过特殊方法__call__,MyPy(和其他兼容的类型检查器)原生支持完整的调用语法。

MyPy: 回调协议

可以使用协议定义灵活的回调类型,这些类型使用Callable[...]语法难以(甚至不可能)表达,例如可变参数、重载和复杂泛型回调。 (...)

只需定义一个具有所需签名的Protocol即可。

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

请注意,Protocol__call__必须包含一个self参数。当将其他签名与Protocol进行比较时,此参数将被忽略。

12
据我所知,Python的类型提示不允许直接这样做,如 typing.Callable 文档中所述。它没有语法来指示可选或关键字参数;这样的函数类型很少用作回调类型。但是,您可以使用 mypy扩展 来实现类似功能:
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
正如上面链接的mypy_extensions文档中所述,扩展的可调用类型现已被弃用。弃用通知表示:“您可以使用回调协议作为替代方案。” - Jasha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接