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

后端 未结 5 1622
忘掉有多难
忘掉有多难 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条回答
  •  萌比男神i
    2020-12-08 13:47

    If we use dis.dis(), we can see how the functions actually behave.

    count_even_digits_spyr03_for():

      7           0 LOAD_CONST               1 (0)
                  3 STORE_FAST               0 (count)
    
      8           6 SETUP_LOOP              42 (to 51)
                  9 LOAD_GLOBAL              0 (str)
                 12 LOAD_GLOBAL              1 (n)
                 15 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
                 18 GET_ITER
            >>   19 FOR_ITER                28 (to 50)
                 22 STORE_FAST               1 (c)
    
      9          25 LOAD_FAST                1 (c)
                 28 LOAD_CONST               2 ('02468')
                 31 COMPARE_OP               6 (in)
                 34 POP_JUMP_IF_FALSE       19
    
     10          37 LOAD_FAST                0 (count)
                 40 LOAD_CONST               3 (1)
                 43 INPLACE_ADD
                 44 STORE_FAST               0 (count)
                 47 JUMP_ABSOLUTE           19
            >>   50 POP_BLOCK
    
     11     >>   51 LOAD_FAST                0 (count)
                 54 RETURN_VALUE
    

    We can see that there's only one function call, that's to str() at the beginning:

    9 LOAD_GLOBAL              0 (str)
    ...
    15 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
    

    Rest of it is highly optimized code, using jumps, stores, and inplace adding.

    What comes to count_even_digits_spyr03_sum():

     14           0 LOAD_GLOBAL              0 (sum)
                  3 LOAD_CONST               1 ( at 0x10dcc8c90, file "test.py", line 14>)
                  6 LOAD_CONST               2 ('count2..')
                  9 MAKE_FUNCTION            0
                 12 LOAD_GLOBAL              1 (str)
                 15 LOAD_GLOBAL              2 (n)
                 18 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
                 21 GET_ITER
                 22 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
                 25 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
                 28 RETURN_VALUE
    

    While I can't perfectly explain the differences, we can clearly see that there are more function calls (probably sum() and in(?)), which make the code run much slower than executing the machine instructions directly.

提交回复
热议问题