【问题标题】:How do I annotate a callable with *args and **kwargs?如何使用 *args 和 **kwargs 注释可调用对象?
【发布时间】:2022-05-13 22:14:04
【问题描述】:

我有一个返回函数的函数。我想找到一个合适的类型注释。但是,返回的函数有*args*kwargsCallable[[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

【问题讨论】:

    标签: python python-typing


    【解决方案1】:

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

    MyPy:Callback Protocols

    协议可用于定义使用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
    

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

    【讨论】:

      【解决方案2】:

      据我所知,python 的输入不允许像 typing.Callable 的文档中所述直接执行此操作:

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

      但你可以像这样使用mypy extensions

      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
      
      

      【讨论】:

      • 如上面链接的mypy_extensions 文档中所述,扩展的可调用类型现在已被弃用。弃用通知说“您可以使用回调协议作为替代。”
      猜你喜欢
      • 2016-08-30
      • 1970-01-01
      • 2012-04-09
      • 2017-03-26
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      • 2017-01-28
      • 2022-01-06
      相关资源
      最近更新 更多