JoePythonKing
JoePythonKing

Reputation: 1210

Why does yield + iter() not produce output?

def myf2():
    for x in "abzdef":
        yield x


#print(list(myf2()))

print(list(iter(myf2,'z')))

I expected ['a', 'b'] but in https://repl.it/languages/python3 I get a wait before the cursor comes back with no output. Python 3.6.3 |Anaconda custom (64-bit)| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)]

Upvotes: 2

Views: 120

Answers (2)

BlueSheepToken
BlueSheepToken

Reputation: 6109

Actually, this gives a memory error.

list(generator) calls the next method until a StopIteration Error is raised.

The next method of iter(myf2, 'z') returns a generator created by myf2 each times it is call. It will never reach 'z', and never ends.

You can check this with print(type(iter(myf2, 'z')))

You will receive a MemoryError

Upvotes: 0

Carcigenicate
Carcigenicate

Reputation: 45760

You can see the problem if you attempt to iterate the return of iter:

for x in iter(myf2, 'z'):
    print(x)

This will print out infinite generator objects, not letters. This was the problem. list would take an infinite amount of time to evaluate an infinite list (or, at least as much time as it takes to crash with a memory error).

Why does this happen? Because calling myf2, which iter does, returns a generator. When you iterate the returned generator, you'll get the letters.

If you wanted to do what you're trying to do, you could use itertool's takewhile:

from itertools import takewhile

def myf2():
    for x in "abzdef":
        yield x


gen = myf2()
print(list(takewhile(lambda x: x != 'z', gen)))

# ['a', 'b']

Upvotes: 1

Related Questions