简体   繁体   English

如何使用类型提示在生成器上注释装饰器?

[英]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: 作为更具体的方法,您可以执行以下操作:

  1. Use Callable type instead of question marks. 使用Callable类型而不是问号。

  2. Use typing.Coroutine for targets and drop the ArbGenerator . 使用typing.Coroutine作为targets并放下ArbGenerator

  3. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM