DEV Community

Cover image for Generate Generators Repeatedly
Modasser Billah
Modasser Billah

Posted on • Originally published at modasserbillah.ml

Generate Generators Repeatedly

Generators are great. We all know it. They save us all the memory lists take up yet give us the same results and more. Well, almost.

The only catch with generators is that they generate the values only once. Let's look at an example.

def generate_numbers(num):
    while num > 0:
        yield num
        num -= 1

The function above gives us a generator. It takes a number as an argument and produces all the numbers from there down to 1.

generate5 = generate_numbers(5)

If we print generate5 it will show us that it holds a generator.

print(generate5)
>>> <generator object generate_numbers at 0x10dcb2b88>

Now we can do something like the following to generate the numbers:

for number in generate5:
    print(number)

And this will print:

5
4
3
2
1

But if you run it again

for number in generate5:
    print(number)

You won't see any output.

Where did it go?

Well, this is what generators do. They generate values on the fly and then stop. You can't run them again and again unless you run generate5 = generate_numbers(5) each time. Generally people will tell you in cases like this you should use a list.

But there's a way around if you insist on using generators yet want repeated outputs. Let's see how.

class NumberGenerator:
    def __init__(self, num):
        self.num = num

    def __iter__(self):
        count = self.num
        while count > 0:
            yield count
            count -= 1

The code from the generate_numbers function is copied over (well, almost with slight class related modifications) to the __iter__ method for the NumberGenerator class. Whenever we loop through an object, it looks up the __iter__ method. If it's there, Python will use it to return an iterator.

So, now you can do something like this to instantiate the class:

generate5 = NumberGenerator(5)

And then loop over it as many times as you want using:

for number in generate5:
    print(number)

Note that this may not be the optimal thing to do all the time but it's an interesting tidbit to know that you can hack a generator this way to work more than once.

Happy hacking!

This post was originally published here

Top comments (0)