путаница с аннотированием функции генератора как итератора

В документации Python typing написано:

В качестве альтернативы аннотируйте свой генератор как имеющий тип возвращаемого значения Iterable [YieldType] или Iterator [YieldType]:

def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1

Я написал очень простой пример печати бесконечного потока. У меня есть функция генератора, которая передается другой функции, а затем вызывается.

from typing import Iterator


def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1


def print_infinite_stream(inf_iterator: Iterator[int]):
    for x in inf_iterator(5):
        print(x)


print_infinite_stream(infinite_stream)

С mypy я получаю две ошибки:

  • ошибка: итератор [int] не вызывается

  • ошибка: аргумент 1 для print_infinite_stream имеет несовместимый тип «Callable [[int], Iterator [int]]»; ожидаемый "Iterator [int]"

Я не понимаю, почему я получаю эти ошибки, поскольку я работал в соответствии с документацией и у меня установлены последние версии python (3.6.5) и mypy (0.590). Что здесь не так?


person David Michael Gang    schedule 03.05.2018    source источник


Ответы (1)


аннотируйте свой генератор как имеющий возвращаемый тип Iterable [YieldType] или Iterator [YieldType]

Функции генератора возвращают генераторы, они сами не являются генераторами. Если вы это сделаете:

reveal_type(infinite_stream), вы получите что-то вроде Callable[[int], Iterator[int]].

Вам нужно возвращаемое значение функции, фактический итератор.

from typing import Iterator


def infinite_stream(start: int) -> Iterator[int]:
    while True:
        yield start
        start += 1


def print_infinite_stream(inf_iterator: Iterator[int]):
    for x in inf_iterator:
        print(x)


print_infinite_stream(infinite_stream(5))

В этом больше смысла, поскольку теперь print_infinite_stream обрабатывает любой итератор, а не только вашу функцию-генератор. Если вы reveal_type(infinite_stream(5)), вы должны получить что-то вроде Iterator[int], а это именно то, что вам нужно.

person ethanhs    schedule 03.05.2018