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

dav*_*bak 6 python generator type-hinting python-3.x

我正在使用生成器作为协程,如 David Beazley 的精彩三重演示(位于http://www.dabeaz.com/coroutines/)中所述,但我不知道如何输入装饰器consumer。这是我到目前为止所拥有的:

\n\n
from typing import Any, Callable, Generator, Iterable\n\nArbGenerator = Generator[Any, Any, Any]\n\ndef consumer(fn: \xe2\x9d\x93) -> \xe2\x9d\x93:\n    @wraps(fn)\n    def start(*args: Any) -> ArbGenerator:\n        c = fn(*args)\n        c.send(None)\n        return c\nreturn start\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用示例,略为:

\n\n
@consumer\ndef identity(target: ArbGenerator) -> ArbGenerator:\n    while True:\n        item = yield\n        target.send(item)\n\n@consumer\ndef logeach(label: Any, target: ArbGenerator) -> ArbGenerator:\n    while True:\n        item = yield\n        print(label, item)\n        target.send(item)\n\npipeline = identity(logeach("EXAMPLE", some_coroutine_sink()))\n
Run Code Online (Sandbox Code Playgroud)\n\n

粗体\xe2\x9d\x93标记了我不确定的地方 - 并且我也不确定我定义的类型ArbGenerator。(问题是,如果没有输入(装饰器)函数consumer本身,我不确定mypy是否使用该装饰器分析任何生成器函数,这就是我不确定的原因ArbGenerator。)

\n\n

我对最紧密的类型感兴趣,比 更好Any,这样当我编写这些协程链时,mypy如果链设置不正确,就会给我很好的警告。

\n\n

(Python 3.5,如果重要的话。)

\n

Kas*_*mvd 2

作为更具体的方式,您可以执行以下操作:

  1. 使用Callable类型而不是问号。

  2. 使用typing.Coroutinefortargets并删除ArbGenerator.

  3. 协程返回一个生成器,返回类型可以是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)
Run Code Online (Sandbox Code Playgroud)

注意:正如文档中也提到的,如果您想使用更精确的语法来注释生成器类型,您可以使用以下语法:

Generator[YieldType, SendType, ReturnType]
Run Code Online (Sandbox Code Playgroud)

阅读更多:https ://docs.python.org/3/library/typing.html#typing.Generator