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

Mar*_*oma 8 python python-typing

我有一个返回函数的函数。我想找到一个合适的类型注释。但是,返回的函数具有*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
Run Code Online (Sandbox Code Playgroud)

ale*_*ame 13

据我所知,python 的打字不允许直接这样做,如以下文档中所述typing.Callable

没有语法来指示可选参数或关键字参数;此类函数类型很少用作回调类型。Callable[..., ReturnType](文字省略号)可用于类型提示可调用函数采用任意数量的参数并返回 ReturnType。

但是你可以像这样使用 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

Run Code Online (Sandbox Code Playgroud)

  • 正如上面链接的“mypy_extensions”文档中所述,扩展的可调用类型现已弃用。弃用通知称“您可以使用回调协议作为替代”。 (2认同)

Mis*_*agi 5

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

MyPy:回调协议

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

只需定义一个具有所需签名Protocol__call__方法。

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
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。 (3认同)