Every use I can think of for Python's itertools.repeat()
class, I can think of another equally (possibly more) acceptable solution to achieve the same effect. For example:
>>> [i for i in itertools.repeat('example', 5)]
['example', 'example', 'example', 'example', 'example']
>>> ['example'] * 5
['example', 'example', 'example', 'example', 'example']
>>> list(map(str.upper, itertools.repeat('example', 5)))
['EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE']
>>> ['example'.upper()] * 5
['EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE', 'EXAMPLE']
Is there any case in which it would be the most appropriate solution? If so, under what circumstances?
The primary purpose of itertools.repeat is to supply a stream of constant values to be used with map or zip:
>>> list(map(pow, range(10), repeat(2))) # list of squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
The secondary purpose is that it gives a very fast way to loop a fixed number of times like this:
for _ in itertools.repeat(None, 10000):
do_something()
This is faster than:
for i in range(10000):
do_something().
The former wins because all it needs to do is update the reference count for the existing None object. The latter loses because the range() or xrange() needs to manufacture 10,000 distinct integer objects.
Note, Guido himself uses that fast looping technique in the timeit() module. See the source at https://hg.python.org/cpython/file/2.7/Lib/timeit.py#l195 :
if itertools:
it = itertools.repeat(None, number)
else:
it = [None] * number
gcold = gc.isenabled()
gc.disable()
try:
timing = self.inner(it, self.timer)