具有不同kwarg的函数的回调协议



我有一个函数,它将callback函数作为参数:

def function(arg1: int, callback):
...

我正在尝试为callback函数添加一个类型提示。现在,传递给该函数的回调函数具有相同的位置args,但kwargs可能完全不同(类型和名称(。

def function1(arg1: int, arg2: str, **kwargs1):
...
def function2(arg1: int, arg2: str, **kwargs2):
...

我正试图编写一个适合这两个函数的回调协议,但到目前为止,我还看不到在夸尔格不同的情况下实现这一点的方法。在这种情况下,有没有办法创建一个统一的回调协议?

您可以创建此回调协议:

from typing_extensions import Protocol

class Callback(Protocol):
def __call__(self, arg1: int, arg2: str, **kwargs): ...

并将提示callback键入为Callback:

def function(arg1: int, callback: Callback): ...

现在,在这三个函数调用中:

def function1(arg1: int, arg2: str, **kwargs1): ...
def function2(arg1: int, arg2: str, **kwargs2): ...
def function3(arg1: int): ...
function(0, function1) # Success.
function(0, function2) # Success.
function(0, function3) # Error.

mypy将为前两个报告成功,但由于缺少arg2,为第三个报告错误。

这里要实现的关键是,关键字arguments参数的名称实际上并不重要。如果我取function2并将arg1重命名为arg_1mypy会抱怨这一点。这是因为function2的公共接口以向后不兼容的方式发生了变化。例如,我必须将任何呼叫站点的arg1=0修改为arg_1=0

但如果我使用相同的函数并将kwargs2重命名为kwargs_2,那么公共接口实际上并没有改变!这是因为最初不可能在调用站点显式引用kwargs/kwargs1/kwargs2参数。举个例子:

function2(arg1=0, arg2="", kwargs2={})

如果我从函数内部转储kwargs2,它实际上会将关键字"kwargs2"映射到{},而不是一个空字典本身。这表明不可能依赖关键字arguments参数的名称。因此,当检查CCD_ 23的公共接口是否与CCD_ 24的公共接口匹配时,CCD_。

至于类型,kwargskwargs1kwargs2都有一个类型为Dict[str, Any]的注释。由于您在所有3个方面都是一致的,因此mypy在这里报告成功,同时还使您能够利用Any来处理特定于function1function2的关键字参数。

最新更新