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.