1

I am trying to wrap my head around generator and yield in python. I understand that a function that has an yield returns a generator object. However if I try to convert that generator object to a list it hangs my machine. I am trying to figure out why that is. And what is a more elegant way if any to convert a generator object to a list.

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

a = fib()
print(type(a))

b = fib()
print(type(b))

print(list(b))

Output

<class 'generator'>
<class 'generator'>

5 Answers 5

4

The problem is that your generator has no end condition (while True and no break)

Even if it could make sense to write such a generator (ex: yield all the decimals of Pi or the Fibonacci sequence I just recognized in your code :)), when you convert it to a list, it loops forever (and eats all the memory too)

BTW: list() is of course the best way to turn a (finite :)) generator to a list object.

Sign up to request clarification or add additional context in comments.

Comments

3

list() can't convert an infinite sequence. You need to add an upper limit to your generator:

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

print list(fib(10))

3 Comments

I haven't come across _ inside a for loop. what does that mean?
@liv2hak It basically means that you don't need the variable, you just need to repeat something n number of times with n being the number supplied to range().
@liv2hak _ is just conventionally used that way, but it is like any other variable name x, i, banana...
3

Since your generator does not have an upper limit, asking a list of it is like asking to list all the numbers of the Fibonacci sequence (which, as was pointed before, is infinite, so it might take some time :)).

So, either put an argument in your fib() generator as explained in another post too, or use something like that for the, say, 10 next values:

b = fib()
[next(b) for _ in range(10)]

2 Comments

This means generator implements __next__ interface just like iterator does. thanks got it
@liv2hak all a generator is suppose to be is a convenient way to define iterators.
1

The problem is your generator - list(fib()) basically goes through all iterations of the generator and places them in a list. Since your generator is an infinite loop, the iterations never stop.

Comments

1

As others have said, your generator will run infinitely. If you tried to convert an infinite generator to a list, it would run ou of memory. The reason you're getting the output you are is because you need to use next()(which was .__next__ in Python 2) to get the next element from the generator. eg.

>>> def gen():
    for i in range(100):
        yield i


>>> g = gen()
>>> next(g)
0
>>> next(g)
1
>>> next(g)
2
>>> 

But you seem to want to create an entire iterable from your generator, in which case you cannot. Python will run out of memory. If you want to convert your generator to a list, it must have an upper limit.

>>> def gen():
    while True:
        yield 0


>>> g = gen()
>>> list(g)
# it gets stuck forever 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.