Here's an interesting example.
Often we just want to repeat an operation n times, and we don't particularly care about the loop counter.
The common approach is to use range to do this.
For example, to repeat something 10 times, we can write:
for _ in range(10):
print('python')
(Here I use the underscore (_) character to indicate I don't care about the loop counter - but _ is a valid variable name, so nothing special going on here)
This works fine, but we have to create a range object, and we can in fact approach this more efficiently using the itertools module.
The function itertools.repeat(obj, n) will basically create a generator that will yield the specified obj, n times.
For example:
import itertools
for s in itertools.repeat('python', 5):
print(s)
import itertools
for s in itertools.repeat('python', 5):
print(s)
Now in the original intent we don't actually care about the loop counter, so we can use None as the object:
for _ in itertools.repeat(None, 5):
print('python')
for _ in itertools.repeat(None, 5):
print('python')
Using itertools.repeat actually offers us better performance.
Let's time some operations where we want to find the maximum value of a sequence of N random numbers.
from itertools import repeat
from timeit import timeit
from timeit import timeit
import random
def find_max_range(n):
random.seed(0)
return max(random.random() for _ in range(n))
def find_max_iter(n):
random.seed(0)
return max(random.random() for _ in repeat(None, n))
print(timeit('find_max_range(10_000)',
globals=globals(), number=1_000))
print(timeit('find_max_iter(10_000)',
globals=globals(), number=1_000))
When I run this, I get the following timings:
- using range: 1.09s
- using repeat: 0.93s
So using repeat is about 14% faster than using range!