我有一个功能
def run_thing(cb: Callback) -> Result:
w: Widget = make_widget()
res: Result = cb(w)
return res
我可以想象两种方法来定义回调类型。
# Option 1: Callable
# https://docs.python.org/3/library/typing.html#annotating-callables
Callback = typing.Callable[[Widget],Result]
# Option 2: Protocol
# https://docs.python.org/3/library/typing.html#typing.Protocol
class Callback(typing.Protocol):
def __call__(self,w: Widget) -> Result:
...
在决定上述两种类型定义时需要考虑哪些细微差别?
Callable
可以用于简单的情况,但对于复杂的签名来说就太有限了。
文档对此进行了解释,该文档还建议使用以下引用和示例片段定义
Protocol
作为替代方案:
Callable 无法表达复杂的签名,例如采用可变数量参数的函数、重载函数或仅具有关键字参数的函数。然而,这些签名可以通过定义一个带有
方法的Protocol
类来表达:__call__()
--- Python 的
文档typing
from collections.abc import Iterable
from typing import Protocol
class Combiner(Protocol):
def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...
def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
for item in data:
...
def good_cb(*vals: bytes, maxlen: int | None = None) -> list[bytes]:
...
def bad_cb(*vals: bytes, maxitems: int | None) -> list[bytes]:
...
batch_proc([], good_cb) # OK
batch_proc([], bad_cb) # Error! Argument 2 has incompatible type because of
# different name and kind in the callback