How can I infinitely loop an iterator in Python, via a generator or other?

Question:

It’s my understanding that using a Generator is the best way to achieve something like this, but I’m open to suggestions.

Specifically, one use case is this: I’d like to print some items alongside another list, of an arbitrary length, truncating the initial iterator as necessary.

Here is working python code that demonstrates the exact example behavior I desire:

    def loop_list(iterable):
        """
        Return a Generator that will infinitely repeat the given iterable.

        >>> l = loop_list(['sam', 'max'])
        >>> for i in range(1, 11):
        ...     print i, l.next()
        ... 
        1 sam
        2 max
        3 sam
        4 max
        5 sam
        6 max
        7 sam
        8 max
        9 sam
        10 max

        >>> l = loop_list(['sam', 'max'])
        >>> for i in range(1, 2):
        ...     print i, l.next()
        ... 
        1 sam
        """
        iterable = tuple(iterable)
        l = len(iterable)
        num = 0
        while num < l:
            yield iterable[num]
            num += 1
            if num >= l:
                num = 0

The Problem / My Question

As you may have noticed, this only works on lists/tuples/iterables that implement __getitem__ (if I’m not mistaken). Ideally, I’d like to be able to pass any iterable, and receive a generator that can properly loop over it’s content.

If there’s a better way to do something like this without a generator, I’m fine with that as well.

Asked By: anonymous coward

||

Answers:

You can use itertools.cycle (source included on linked page).

import itertools

a = [1, 2, 3]

for element in itertools.cycle(a):
    print element

# -> 1 2 3 1 2 3 1 2 3 1 2 3 ...
Answered By: Jon Gauthier

You can iterate over a list, appending an item to it:

somelist = [item1, item2, item3]
for item in somelist:
    somelist.append(item)
    do_something()
Answered By: Christophe Slychan

Try this-

L = [10,20,30,40]

def gentr_fn(alist):
    while 1:
        for j in alist:
            yield j

a = gentr_fn(L)
print a.next()
print a.next()
print a.next()
print a.next()
print a.next()
print a.next()
print a.next()

>>gentr_fn(x,y)
10 20 30 40 10 20 30 ...
Answered By: Aby

You can use module to keep it simple.
Just make sure not to start iterating from 0.


my_list = ['sam', 'max']

for i in range(1, 100):
    print(my_list[(i % len(my_list))-1])


Answered By: avi_k
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.