Genrators
Fibonacci Sequence
from functools import lru_cache
@lru_cache()
def fib_recursive(n):
if n <= 1:
return 1
else:
return fib_recursive(n-1) + fib_recursive(n-2)let's create an iterator approach so we can iterate over the sequence, but without materializing it
def fib_gen(n):
fib_0 = 1
yield fib_0
fib_1 = 1
yield fib_1
for i in range(n-1):
fib_0, fib_1 = fib_1, fib_0 + fib_1
yield fib_1
[num for num in fib_gen(7)]
Out:
[1, 1, 2, 3, 5, 8, 13, 21]
Making an Iterable from a Generator
As we now know, generators are iterators.
This means that they become exhausted - so sometimes we want to create an iterable instead.
There's no magic here, we simply have to implement a class that implements the iterable protocol:
But, sq was an iterator - so now it's been exhausted, To restart the iteration we have to create a new instance of the generator,let's wrap this in an iterable:
Card Deck
We can now make it into an iterable:
One thing we don't have here is the support for reversed,but we can add it in by implementing the __reversed__ method and returning an iterator that iterates the deck in reverse order.
Yield From
Example
Here's an example where using yield from can be quite effective.
In this example we need to read car brands from multiple files to get it as a single collection.
We might do it this way:
We can simplify our function by using yield from:
So, we are going to create generators that can read each line of the file, and yield a clean result, and we'll yield from that generator:
As you can see, this generator function will clean each line of the file before yielding it. Let's try it with a single file and make sure it works:
Ok, that works. So now, we can proceed with our overarching generator function as before, except we'll yield from our generators, instead of directly from the file iterator:
Other examples
Last updated
Was this helpful?
