使用kwargs的python键入签名(typing.Callable)

时间:2019-09-07 21:31:47

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

我大量使用python 3的python输入支持。

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

请检查下面的代码和注释。

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)

2 个答案:

答案 0 :(得分:3)

您可能正在寻找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"

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

答案 1 :(得分:-3)

简单的解决方案:对 kwargs 使用类型 Any

示例:

from typing import Any, Callable

def function_executor(
        val: int,
        kwargs: dict,
        fn: Callable[[int, Any], bool]):
    return fn(val, **kwargs)

def fn1(val, kw1, kw2):
    return str(val + kw1 + kw2)

kwargs = {'kw1': '2', 'kw2': '3'}

print(function_executor('1', kwargs, fn1))

输出:

123