[英]How to annotate a decorator on a generator using type hinting?
I'm working with generators-as-coroutines as described in the excellent triplet of presentations by David Beazley (at http://www.dabeaz.com/coroutines/ ) and I can't figure out how to type the decorator consumer
. 我正在使用David Beazley出色的演讲三联体中所述的generators-as-coroutines(位于http://www.dabeaz.com/coroutines/ ),但我不知道如何输入装饰consumer
。 Here's what I have so far: 这是我到目前为止的内容:
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
Example of use, kind of abridged: 使用示例,简称:
@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()))
Bold ❓
marks where I'm unsure - and I'm also unsure about the type I defined ArbGenerator
. 粗体❓
表示我不确定的地方-我也不确定我定义的ArbGenerator
类型。 (Problem is, without the (decorator) function consumer
itself typed, I'm not sure mypy
is analyzing any generator function with that decorator so that's why I'm unsure about ArbGenerator
.) (问题在于,如果没有输入(装饰器)函数consumer
本身,我不确定mypy
是否正在使用该装饰器分析任何生成器函数,所以这就是为什么我不确定ArbGenerator
的原因。)
I'm interested in the tightest type, something better than Any
, so that when I compose chains of these coroutines mypy
will give me nice warnings if the chain isn't set up right. 我对最紧密的类型感兴趣,它比Any
更好,因此当我mypy
这些协程的链时,如果链设置不正确, mypy
会给我很好的警告。
(Python 3.5 if it matters.) (如果重要,请使用Python 3.5。)
As a more specific way, here are few things you can do: 作为更具体的方法,您可以执行以下操作:
Use Callable
type instead of question marks. 使用Callable
类型而不是问号。
Use typing.Coroutine
for targets
and drop the ArbGenerator
. 使用typing.Coroutine
作为targets
并放下ArbGenerator
。
Coroutines return a generator and the return type could be a Generator
or one of its supertypes 协程返回一个生成器,返回类型可以是一个Generator
或它的超类型之一
The reason that you should use callable instead of question marks is that fn
is supposed to be a callable object at first and that's why you're wrapping it with a decorator. 之所以应该使用callable而不是问号,是因为fn
首先应该是一个可调用的对象,这就是为什么要用装饰器包装它。 The Coroutine
will be created after calling the object and the return type is/should be obviously a callable object as well. 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)
Note : As it's also mentioned in documentation, if you want to use a more precise syntax for annotating the generator type you can use the following syntax: 注意 :正如文档中也提到的那样,如果要使用更精确的语法来注释生成器类型,则可以使用以下语法:
Generator[YieldType, SendType, ReturnType]
Read more: https://docs.python.org/3/library/typing.html#typing.Generator 了解更多: https : //docs.python.org/3/library/typing.html#typing.Generator
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.