我大量使用python 3提供的python类型支持.

最近,我试图将一个函数作为参数传递,但我找不到使用kwargsintyping.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)

推荐答案

你可能在找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

如果您try 使用mypy对该程序进行类型判断,最后一行将出现以下错误(当然是神秘的):

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

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

Python-3.x相关问答推荐

无法使用Python slack 螺栓SDK读取在 slack 通道中收到的消息

谁能解释一下这个带邮编的多功能环路?

PythonPandas READ_EXCEL空数据帧

Python-Django 设置 Pandas DataFrame 的多索引不会分组/合并最后一个索引

在不使用 split 函数的情况下从字符串中分割逗号(','),句号('.')和空格(' '),将字符串的单词附加到列表中

Django中自动设置/更新字段

我想使用命令提示符安装 cv2

try 使用 GEKKO 求解非线性方程组.系统有多种解决方案,但 GEKKO 给出了错误的解决方案.我该如何解决?

根据按不同列中的值分组的平均值划分 DataFrame

如何在 histplot 中标记核密度估计

使用 RANSAC 在激光雷达点云中查找电力线

为什么最简单的流光示例会出错?

判断对 python 3 支持的要求

使用 Sympy 方程进行绘图

Python的max函数有多高效

当默认 pip 为 pip2 时,升级 pip3 的正确格式是什么?

同步调用协程

finally 总是在 try 块返回之前运行,那么为什么 finally 块中的更新不会影响 try 块返回的变量的值呢?

无法解码 Python Web 请求

十六进制字符串到 Python 3.2 中的带符号整数?