Why is a `for` loop so much faster to count True values?

后端 未结 5 1636
忘掉有多难
忘掉有多难 2020-12-08 13:20

I recently answered a question on a sister site which asked for a function that counts all even digits of a number. One of the other answers contained two functions (which t

5条回答
  •  盖世英雄少女心
    2020-12-08 13:50

    All your functions contain equal number of calls to str(n) (one call) and c in "02468" (for every c in n). Since then I would like to simplify:

    import timeit
    
    num = ''.join(str(i % 10) for i in range(1, 10000001))
    
    def count_simple_sum():
        return sum(1 for c in num)
    
    def count_simple_for():
        count = 0
        for c in num:
            count += 1
        return count
    
    
    print('For Loop Sum:', timeit.timeit(count_simple_for, number=10))
    print('Built-in Sum:', timeit.timeit(count_simple_sum, number=10))
    

    sum is still slower:

    For Loop Sum: 2.8987821330083534
    Built-in Sum: 3.245505138998851
    

    The key difference between these two functions is that in count_simple_for you are iterating only throw num with pure for loop for c in num, but in count_simple_sum your are creating a generator object here (from @Markus Meskanen answer with dis.dis):

      3 LOAD_CONST               1 ( at 0x10dcc8c90, file "test.py", line 14>)
      6 LOAD_CONST               2 ('count2..')
    

    sum is iterating over this generator object to sum the elements produced, and this generator is iterating over elements in num to produce 1 on each element. Having one more iteration step is expensive because it requires to call generator.__next__() on each element and these calls are placed into try: ... except StopIteration: block which also adds some overhead.

提交回复
热议问题