Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

confusion of annotating generator function as iterator

In the python typing documentation it is written:

Alternatively, annotate your generator as having a return type of either Iterable[YieldType] or Iterator[YieldType]:

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

I wrote a very easy example of printing an infinite stream. I have a generator function which is passed to another function and then called.

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)

With mypy i get two errors:

  • error:Iterator[int] not callable

  • error:Argument 1 to "print_infinite_stream" has incompatible type "Callable[[int], Iterator[int]]"; expected "Iterator[int]"

I am confused why i am getting these errors as i worked according to the documentation and have the latest python (3.6.5) and mypy (0.590) installed. What is wrong here?

like image 919
David Michael Gang Avatar asked May 03 '18 12:05

David Michael Gang


People also ask

What is difference between generator and iterator?

Iterators are the objects that use the next() method to get the next value of the sequence. A generator is a function that produces or yields a sequence of values using a yield statement. Classes are used to Implement the iterators. Functions are used to implement the generator.

Is generator an iterator or iterable?

A generator is technically an iterator, basically, it's a way to define iterator protocol in a compact way. A classic iterator will be defined using a class with __iter__ and __next__ methods, with a generator you can do this with just a function with yield statements or generator expressions.

How iterator can be used to generate the generator?

Yes, We can create a generator by using iterators in python Creating iterators is easy, we can create a generator by using the keyword yield statement. Python generators are an easy and simple way of creating iterators. and is mainly used to declare a function that behaves like an iterator.

Why generators are faster than iterators?

Iterators allow lazy evaluation, only generating the next element of an iterable object when requested. This is useful for very large data sets. Iterators and generators can only be iterated over once. Generator Functions are better than Iterators.


1 Answers

annotate your generator as having a return type of either Iterable[YieldType] or Iterator[YieldType]

Generator functions return generators, they are not generators themselves. If you do:

reveal_type(infinite_stream), you will get something like Callable[[int], Iterator[int]].

What you want is the return value of the function, the actual iterator.

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))

This makes more sense as now print_infinite_stream handles any iterator, not just your generator function. If you reveal_type(infinite_stream(5)) you should get something like Iterator[int], which is exactly what you want.

like image 184
ethanhs Avatar answered Nov 14 '22 21:11

ethanhs