Skip to content
Advertisement

How to write a generator class?

I see lot of examples of generator functions, but I want to know how to write generators for classes. Lets say, I wanted to write Fibonacci series as a class.

JavaScript

Output:

JavaScript

Why is the value self.a not getting printed? Also, how do I write unittest for generators?

Advertisement

Answer

How to write a generator class?

You’re almost there, writing an Iterator class (I show a Generator at the end of the answer), but __next__ gets called every time you call the object with next, returning a generator object. Instead, to make your code work with the least changes, and the fewest lines of code, use __iter__, which makes your class instantiate an iterable (which isn’t technically a generator):

JavaScript

When we pass an iterable to iter(), it gives us an iterator:

JavaScript

To make the class itself an iterator, it does require a __next__:

JavaScript

And now, since iter just returns the instance itself, we don’t need to call it:

JavaScript

Why is the value self.a not getting printed?

Here’s your original code with my comments:

JavaScript

So every time you called next(f) you got the generator object that __next__ returns:

JavaScript

Also, how do I write unittest for generators?

You still need to implement a send and throw method for a Generator

JavaScript

And now:

JavaScript

So let’s implement a generator object, and leverage the Generator abstract base class from the collections module (see the source for its implementation), which means we only need to implement send and throw – giving us close, __iter__ (returns self), and __next__ (same as .send(None)) for free (see the Python data model on coroutines):

JavaScript

and using the same tests above:

JavaScript

Python 2

The ABC Generator is only in Python 3. To do this without Generator, we need to write at least close, __iter__, and __next__ in addition to the methods we defined above.

JavaScript

Note that I copied close directly from the Python 3 standard library, without modification.

Advertisement