pythonic way to do something N times without an index variable?

Coding StyleFor LoopPython

Coding Style Problem Overview


Every day I love python more and more.

Today, I was writing some code like:

for i in xrange(N):
    do_something()

I had to do something N times. But each time didn't depend on the value of i (index variable). I realized that I was creating a variable I never used (i), and I thought "There surely is a more pythonic way of doing this without the need for that useless index variable."

So... the question is: do you know how to do this simple task in a more (pythonic) beautiful way?

Coding Style Solutions


Solution 1 - Coding Style

A slightly faster approach than looping on xrange(N) is:

import itertools

for _ in itertools.repeat(None, N):
    do_something()

Solution 2 - Coding Style

Use the _ variable, as I learned when I asked this question, for example:

# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
    product *= num
print product

Solution 3 - Coding Style

I just use for _ in range(n), it's straight to the point. It's going to generate the entire list for huge numbers in Python 2, but if you're using Python 3 it's not a problem.

Solution 4 - Coding Style

since function is first-class citizen, you can write small wrapper (from Alex answers)

def repeat(f, N):
    for _ in itertools.repeat(None, N): f()

then you can pass function as argument.

Solution 5 - Coding Style

The _ is the same thing as x. However it's a python idiom that's used to indicate an identifier that you don't intend to use. In python these identifiers don't takes memor or allocate space like variables do in other languages. It's easy to forget that. They're just names that point to objects, in this case an integer on each iteration.

Solution 6 - Coding Style

I found the various answers really elegant (especially Alex Martelli's) but I wanted to quantify performance first hand, so I cooked up the following script:

from itertools import repeat
N = 10000000

def payload(a):
    pass

def standard(N):
    for x in range(N):
        payload(None)

def underscore(N):
    for _ in range(N):
        payload(None)

def loopiter(N):
    for _ in repeat(None, N):
        payload(None)

def loopiter2(N):
    for _ in map(payload, repeat(None, N)):
        pass

if __name__ == '__main__':
    import timeit
    print("standard: ",timeit.timeit("standard({})".format(N),
        setup="from __main__ import standard", number=1))
    print("underscore: ",timeit.timeit("underscore({})".format(N),
        setup="from __main__ import underscore", number=1))
    print("loopiter: ",timeit.timeit("loopiter({})".format(N),
        setup="from __main__ import loopiter", number=1))
    print("loopiter2: ",timeit.timeit("loopiter2({})".format(N),
        setup="from __main__ import loopiter2", number=1))

I also came up with an alternative solution that builds on Martelli's one and uses map() to call the payload function. OK, I cheated a bit in that I took the freedom of making the payload accept a parameter that gets discarded: I don't know if there is a way around this. Nevertheless, here are the results:

standard:  0.8398549720004667
underscore:  0.8413165839992871
loopiter:  0.7110594899968419
loopiter2:  0.5891903560004721

so using map yields an improvement of approximately 30% over the standard for loop and an extra 19% over Martelli's.

Solution 7 - Coding Style

Assume that you've defined do_something as a function, and you'd like to perform it N times. Maybe you can try the following:

todos = [do_something] * N  
for doit in todos:  
    doit()

Solution 8 - Coding Style

What about a simple while loop?

while times > 0:
    do_something()
    times -= 1

You already have the variable; why not use it?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManuel AraozView Question on Stackoverflow
Solution 1 - Coding StyleAlex MartelliView Answer on Stackoverflow
Solution 2 - Coding StyleGreenMattView Answer on Stackoverflow
Solution 3 - Coding StyleL̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳View Answer on Stackoverflow
Solution 4 - Coding StyleAnycornView Answer on Stackoverflow
Solution 5 - Coding StyleKhorkrakView Answer on Stackoverflow
Solution 6 - Coding StylejapsView Answer on Stackoverflow
Solution 7 - Coding StyleCox ChenView Answer on Stackoverflow
Solution 8 - Coding StyleCarlos RamirezView Answer on Stackoverflow