1

I'm still new to generators in python. I was trying out one on my own and tried to something really simple:

def fib(a):
...     if a==0 or a==1:return 1
...     yield fib(a-1)+fib(a-2)
print(list(fib(5))

This code gave me this error:

TypeError: unsupported operand type(s) for +: 'generator' and 'generator'

Can't generators be used in this manner?

2
  • Change print(list(fib(5)) to print(list(fib(5))). Commented Jul 16, 2018 at 13:19
  • Try to generate the Fibonacci sequence without recursion and it will work as a generator. Commented Jul 16, 2018 at 13:21

3 Answers 3

6

Calling a generator function doesn't produce the next value. It produces a generator object, a specialist version of an iterator object. You have, in effect, something that wraps a paused function.

To get another value from that function, you'd have to call next(iterator) on the object or use something like list(iteratort) or for ... in iterator to loop over the object and get the values out. See What does the "yield" keyword do? for more details.

So here, the you'd have to use next(fib(a-1)) + next(fib(a-2)) to get the two recursive values out. That'll also fail, because your termination case (a == 0 or a == 1) uses return (translated into the value of a StopIteration exception) and not yield; you'd have to fix that too.

And this highlights why your recursive function should not be a generator function. Your function doesn't produce a series of values to iterate over. There's just one result mfor a given argument value. You'd be far better off to just use return and not yield.

If you wanted to generate a sequence of fibonacci numbers, the function argument would need to be seen as a limit; "give me the first n fibonacci numbers". The following iterative function does that:

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

This would give you a list of the first n fibonacci numbers, as a generator:

>>> f = first_n_fibonacci(5)
>>> f
<generator object first_n_fibonacci at 0x10b2c8678>
>>> next(f)
1
>>> next(f)
1
>>> list(f)
[2, 3, 5]

or you could use the argument to produce all fibonacci values up to a limit, or to produce an endless generator of fibonacci numbers. None of those would require recursion, a loop like the above suffices.

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

1 Comment

Oh okay i get it now, I got confused with how return works. Thank you
1

Generators are meant to be used for iterations, and yet by adding two of the returning values from fib you are trying to use it as a scalar value, which is confirmed by your terminal condition (where a equals to 0 or 1) also returning a scalar value.

You should simply use return in this case.

def fib(a):
    if a==0 or a==1:return 1
    return fib(a-1)+fib(a-2)
print(fib(5))

Comments

0

If you do want to use a generator, you need to think about outputting a sequence, and not a single value. Do you want your fib(a) to output the ath fib number or the the 1st, 2nd, 3rd, 4th, 5th ... ath fib number? If the latter, then generators are good for this.

Here is an example generator for the Fibonacci numbers from the 1st to the nth number.

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

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.