How to Iterate over a Generator Twice

Hey Finxters! It is time for another Python subject that will come up for sure within your Python developer career.

Problem Formulation: How to iterate over a generator twice?

Then we will look at three solutions on how we can iterate twice, or even multiple times, over a generator or iterator.

First, we must understand that a generator in python is a special routine that can be used to control the iteration behaviour of a loop.

In this article we are going to focus on the itertool module and the various ways it is used in the real world. This module is preinstalled in Python so we only need to import it. We will be looking closely at itertools.repeat(), itertool.count and itertools.product. Each one of these generate different ways that we can iterate through a list, tuple or dictionary.

Method 1

In this first example, we are going to use the itertools.repeat() and how it is used in iteration. itertools.repeat() makes an iterator that returns an object over and over again. 

It runs indefinitely unless the times argument is specified. It is used as an argument to map() for invariant parameters to the called function. It can also be used with zip() to create an invariant part of a tuple record. This makes it invaluable for what we are about to do.

Take a look at the code below:

def repeat(object, times=None):
    # repeat(10, 3) --> 10 10 10
    if times is None:
        while True:
            yield object
    else:
        for i in range(times):
            yield object

list(map(pow, range(10), repeat(2)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Above, I have defined two arguments inside the definition of repeat(object, times=None), given my if-else statement, asking repeat to see how many times I want to have it go over my object, and if I do not want anything to happen (None), it will yield that objects expression list back to me, in this case nothing or it will go over my object a number of times before it returns back to me a repeated object. I have called my solution inside of the above function that asks for a list of 10 numbers to their powers then repeated two times.

Method 2

The way it is written above does certainly look nice but it is also one that a beginner programmer would write. The following example will do what the above code example can but with less code for a truly pythonic code:

import itertools
squares = list(map(pow, range(10), itertools.repeat(2)))
print(squares)

The output is:

squares = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Those three lines represent the same code as above. Isn’t that amazing! We took less code to get the same results as the one above!

The left-to-right evaluation order of the iterables is guaranteed. This makes possible an idiom for clustering a data series into n-length groups using zip(*[iter(s)]*n). This repeats the same iterator n times so that each output tuple has the result of n calls to the iterator. This has the effect of dividing the input into n-length chunks. Since, I asked for 10 numbers with a repeat of 5 my output above is correct.

Method 3

Yet another example of using itertools.repeat() is:

import itertools

data = list(zip(range(10), itertools.repeat(5)))
print(data)

It returns an iterator of tuples where the number of iterables from list 1 is matched with list 2. The iterator stops when the shortest list is exhausted. So, the output to this code is:

data = [ (0,5),
	 (1,5),
	 (2,5),
	 (3,5),
	 (4,5),
	 (5,5),
	 (6,5),
	 (7,5),
	 (8,5),
         (9,5)]

This method is used if you would like to have a repeat of a particular value or have an invariant part of a tuple record.

Conclusion

As we can see, itertools is an important tool to use if we want to create repeats with a generator in Python. We can create squares as we saw above in two different methods and we can zip together two lists with an invariant value and print the output.

Python has many tools that can make it easier to do your work on a daily basis. From creating a record and squares using a map() function. We are able to do this with Python in a short amount of code and make it simple. I encourage you to read Python’s official documentation and practice around a little bit playing with itertools until you are comfortable with using it in your programming.

Thank you for joining me on this journey of itertools.repeat(). There are a ton of other tools you can use in place of repeat(). Though I would be careful! Some of these methods can only be used once in a program so you need to be careful when using them! Others will repeat indefinitely unless told otherwise! Carefully review which one would fit your application the best then use that method. This takes a little trial and error but it will make you a better Python programmer in the end!