带有kwargs的函数的python类型签名(typing.Callable)

带有kwargs的函数的python类型签名(typing.Callable),python,python-3.x,python-typing,Python,Python 3.x,Python Typing,我大量使用Python3提供的python类型支持 最近我试图将函数作为参数传递,但在键入.Callable签名中使用kwargs没有任何帮助 请检查下面的代码和注释 导入键入 #一些具有单属性类型的函数 def fn1作为参数,并带有kwargs(a:int,b:float)->float: 返回a+b #一些具有单属性类型的函数 def fn2作为参数,带有kwargs(a:int,b:float)->float: 返回a*b #将可调用项获取为arg的函数 #这适用于打字 def函数执行器

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

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

请检查下面的代码和注释

导入键入
#一些具有单属性类型的函数
def fn1作为参数,并带有kwargs(a:int,b:float)->float:
返回a+b
#一些具有单属性类型的函数
def fn2作为参数,带有kwargs(a:int,b:float)->float:
返回a*b
#将可调用项获取为arg的函数
#这适用于打字
def函数执行器(
答:int,
b:浮动,
fn:typing.Callable[[int,float],float]):
返回fn(a,b)
#但是如果我想给我的kwargs命名呢
#(以下类似的内容不起作用)
# ... 这将帮助我了解更复杂的场景
# ... 还是我对蟒蛇有很多期待;)
def函数执行器(
答:int,
b:浮动,
fn:typing.Callable[[a:int,“b:float],float]):
返回fn(a=a,b=b)

您可能正在寻找

简言之,当您想要用复杂的签名来表示可调用时,您需要做的是创建一个自定义协议,该协议定义了一个具有您想要的精确签名的
\uuuuuuuuuuuuuuuuuuuuuuu
方法

例如,在您的情况下:

来自输入导入协议
#或者,如果您想支持Python 3.7及以下版本,请安装类型扩展
#通过pip访问模块,并执行以下操作:
从输入扩展导入协议
类MyCallable(协议):
定义调用(self,a:int,b:float)->float:。。。
定义良好(a:int,b:float)->float:。。。
定义错误(x:int,y:float)->float:。。。
def函数执行器(a:int,b:float,fn:MyCallable)->float:
返回fn(a=a,b=b)
函数执行器(1,2.3,好)#好!
函数执行器(1,2.3,坏)#错误
如果您尝试使用mypy对该程序进行类型检查,则在最后一行会出现以下错误(当然是神秘的):

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

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

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

例子: 输出:
123

定义函数时,指定其签名,现在包括参数的类型。将dict的结构指定为参数没有什么价值,尤其是
**kwargs
,它只收集命名的参数,即它取决于函数的调用方式。改用其他适当的特定类型(例如NamedTuple、Dataclass、Enum、custom类),也就是说,像通常在某些情况下使用NamedTuple作为参数一样明确说明每个参数,在某些情况下,这是一种救世主。但是我很好奇上面的东西是否被支持,因为我需要定义一些遗留函数。如果它根本不受支持,请让我知道,因为这可能会更有帮助。这一个?那么在这种情况下,更简单的解决方案将是根本不使用打字:)哈哈,很公平。也许我提出的解决办法不是一个好办法
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))