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

前端 未结 8 1140
一整个雨季
一整个雨季 2020-12-02 08:11

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 som

相关标签:
8条回答
  • 2020-12-02 08:43

    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.

    0 讨论(0)
  • 2020-12-02 08:44

    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.

    0 讨论(0)
  • 2020-12-02 08:46

    What about a simple while loop?

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

    You already have the variable; why not use it?

    0 讨论(0)
  • 2020-12-02 08:48

    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.

    0 讨论(0)
  • A slightly faster approach than looping on xrange(N) is:

    import itertools
    
    for _ in itertools.repeat(None, N):
        do_something()
    
    0 讨论(0)
  • 2020-12-02 08:52

    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()
    
    0 讨论(0)
提交回复
热议问题