我有一个函数,它将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_1
,mypy
会抱怨这一点。这是因为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_。
至于类型,kwargs
、kwargs1
和kwargs2
都有一个类型为Dict[str, Any]
的注释。由于您在所有3个方面都是一致的,因此mypy
在这里报告成功,同时还使您能够利用Any
来处理特定于function1
或function2
的关键字参数。