【问题标题】:python typing signature (typing.Callable) for function with kwargs带有kwargs的函数的python类型签名(typing.Callable)
【发布时间】:2019-09-07 21:31:47
【问题描述】:

我大量使用来自 python 3 的 python 类型支持。

最近我试图将函数作为参数传递,但在 typing.Callable 签名中使用 kwargs 没有任何帮助。

请检查下面的代码和 cmets。

import typing

# some function with singnature typing
def fn1_as_arg_with_kwargs(a: int, b: float) -> float:
    return a + b

# some function with singnature typing
def fn2_as_arg_with_kwargs(a: int, b: float) -> float:
    return a * b

# function that get callables as arg
# this works with typing
def function_executor(
        a: int, 
        b: float, 
        fn: typing.Callable[[int, float], float]):
    return fn(a, b)

# But what if I want to name my kwargs 
# (something like below which does not work)
# ... this will help me more complex scenarios 
# ... or am I expecting a lot from python3 ;)
def function_executor(
        a: int, 
        b: float, 
        fn: typing.Callable[["a": int, "b": float], float]):
    return fn(a=a, b=b)

【问题讨论】:

  • 当你定义一个函数时,你指定它的签名,现在包括参数的类型。将 dict 的结构指定为参数没有什么价值,尤其是 **kwargs,它只是收集命名的 args,即它取决于函数的调用方式。改用其他适当和特定的类型(例如 NamedTuple、Dataclass、Enum、自定义类),也就是说像往常一样显式每个参数
  • 我在某些情况下确实使用 NamedTuple 作为参数,这在某些情况下是一个救星。但是很好奇是否支持上述内容,因为我需要 typedef 一些遗留功能。如果根本不支持,请告诉我,因为这可能更有帮助。

标签: python python-3.x python-typing


【解决方案1】:

您可能正在寻找Callback protocols

简而言之,当您想表达一个具有复杂签名的可调用对象时,您要做的是创建一个自定义协议,该协议定义一个具有您想要的精确签名的 __call__ 方法。

例如,在您的情况下:

from typing import Protocol

# Or, if you want to support Python 3.7 and below, install the typing_extensions
# module via pip and do the below:
from typing_extensions import Protocol

class MyCallable(Protocol):
    def __call__(self, a: int, b: float) -> float: ...

def good(a: int, b: float) -> float: ...

def bad(x: int, y: float) -> float: ...


def function_executor(a: int, b: float, fn: MyCallable) -> float:
    return fn(a=a, b=b)

function_executor(1, 2.3, good)  # Ok!
function_executor(1, 2.3, bad)   # Errors

如果您尝试使用 mypy 对该程序进行类型检查,您将在最后一行收到以下(不可否认的)错误:

Argument 3 to "function_executor" has incompatible type "Callable[[int, float], float]"; expected "MyCallable"

(回调协议有点新,所以希望错误消息的质量会随着时间的推移而提高。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-08
    • 2016-02-16
    • 2016-10-27
    • 1970-01-01
    相关资源
    最近更新 更多