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.
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 ...
You can iterate over a list, appending an item to it:
somelist = [item1, item2, item3]
for item in somelist:
somelist.append(item)
do_something()
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 ...
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])
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.
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 ...
You can iterate over a list, appending an item to it:
somelist = [item1, item2, item3]
for item in somelist:
somelist.append(item)
do_something()
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 ...
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])