我用的发电机,作为协同程序工作作为(在http://www.dabeaz.com/coroutines/)由大卫比兹利演讲的优秀三重描述,我无法弄清楚如何键入装饰consumer
。这是我到目前为止有:
from typing import Any, Callable, Generator, Iterable
ArbGenerator = Generator[Any, Any, Any]
def consumer(fn: ❓) -> ❓:
@wraps(fn)
def start(*args: Any) -> ArbGenerator:
c = fn(*args)
c.send(None)
return c
return start
使用示例,那种删节:
@consumer
def identity(target: ArbGenerator) -> ArbGenerator:
while True:
item = yield
target.send(item)
@consumer
def logeach(label: Any, target: ArbGenerator) -> ArbGenerator:
while True:
item = yield
print(label, item)
target.send(item)
pipeline = identity(logeach("EXAMPLE", some_coroutine_sink()))
大胆❓
标记出我不确定 - 我也不确定我定义ArbGenerator
类型。 (问题是,没有(装饰)函数consumer
本身类型的,我不知道mypy
是分析与装饰任何发生器功能,所以这就是为什么我不能确定ArbGenerator
。)
我感兴趣的是最严格的类型,东西比Any
好,所以,当我撰写这些协同程序链mypy
会给我很好的警告,如果链条没有树立正确的。
(Python的3.5,如果它很重要。)
作为更具体的方式,这里有几件事情可以做:
Callable
而不是键入问号。typing.Coroutine
为targets
并删除ArbGenerator
。Generator
或它的超类型之一你应该使用问号可调用的原因是,fn
应该是在第一个调用对象,这就是为什么你与装饰加以包装。该Coroutine
将调用对象的情况下创建并返回类型为/应该是显然是一个可调用对象为好。
from typing import Any, Callable,Generator, Coroutine
from functools import wraps
def consumer(fn: Callable) -> Callable:
@wraps(fn)
def start(*args: Any) -> Coroutine:
c = fn(*args) # type: Coroutine
c.send(None)
return c
return start
@consumer
def identity(target: Coroutine) -> Generator:
while True:
item = yield
target.send(item)
@consumer
def logeach(label: Any, target: Coroutine) -> Generator:
while True:
item = yield
print(label, item)
target.send(item)
注意:因为它是在文档中还提到,如果你想使用更精确的语法标注,您可以使用下面的语法发电机类型:
Generator[YieldType, SendType, ReturnType]
了解更多:https://docs.python.org/3/library/typing.html#typing.Generator