我有一个函数应该接收另一个函数作为参数。我将该参数注释定义为:
input_function: Callable[
[
Optional[InputType],
Optional[Sequence[str]],
Optional[bool]
],
Awaitable[str]
] = func
同时,我的 func
函数的定义如下:
async def func(input_type: InputType = None, formats: Sequence[str] = (), *, hide: bool = False) -> str: ...
函数签名和参数注释应该相同。但是,当我仅使用一个参数调用该函数时(因为所有参数都是可选的),PyCharm 表示存在未填充的参数:
Protocol
的
__call__
,而不是
Callable
。
from typing import Protocol
class InputFunction(Protocol):
async def __call__(self, input_type: InputType = None, formats: Sequence[str] = (), *, hide: bool = False) -> str: ...
input_function: InputFunction = func
Callable
类型只能表达有限种类的签名:显式位置参数(例如
Callable[[A, B], R]
)或任意参数(例如
Callable[..., R]
)。将其参数之一键入为
Optional[T]
意味着它必须是“a
T
或
None
”,而不是可以省略。相比之下,
Protocol
的
__call__
方法允许使用常规定义语法定义签名,包括其所有功能,例如默认值。
虽然回调协议
协议可用于定义难以(甚至不可能)使用
Callable[...]
语法表达的灵活回调类型,例如可变参数、重载和复杂的泛型回调。它们是用特殊的__call__
成员定义的:
Protocol
是一个类,但它在结构上匹配:仅使用
__call__
方法定义它仅编码“具有相同签名的可调用对象”,并且相同签名的函数也满足这一点。请注意,
self
参数在
__call__
定义中是必需的,但不用于检查签名是否匹配。