while循环或同一个命令N次

While loop or the same command N times

我目前正在尝试 cleanup/improve 一些我终于开始工作的代码。

在 while 循环和同一命令反复写入一定次数之间,两者中哪一个更快。

EG.

count = 0
while count < 10:
    print('hello')
    count += 1

print('hello')
print('hello')
print('hello')
print('hello')
print('hello')
print('hello')
print('hello')
print('hello')
print('hello')
print('hello')

while 循环更简洁但速度更快吗?我对此还很陌生,所以我的理解是,就上述程序代码而言,while 循环总共 运行 32 条语句,而打印语句只 运行 10 次:

  1. count is initially set to zero
  2. while evaluates count to be less than 10 (0)
  3. hello is printed
  4. count is incremented by one
  5. while evaluates count to be less than 10 (1)
  6. hello is printed
  7. count is incremented by one
  8. while evaluates count to be less than 10 (2)
  9. hello is printed
  10. count is incremented by one
  11. while evaluates count to be less than 10 (3)
  12. hello is printed
  13. count is incremented by one
  14. while evaluates count to be less than 10 (4)
  15. hello is printed
  16. count is incremented by one
  17. while evaluates count to be less than 10 (5)
  18. hello is printed
  19. count is incremented by one
  20. while evaluates count to be less than 10 (6)
  21. hello is printed
  22. count is incremented by one
  23. while evaluates count to be less than 10 (7)
  24. hello is printed
  25. count is incremented by one
  26. while evaluates count to be less than 10 (8)
  27. hello is printed
  28. count is incremented by one
  29. while evaluates count to be less than 10 (9)
  30. hello is printed
  31. count is incremented by one
  32. while evaluates count to no longer be less than 10 (10) While loop breaks out and processing ends

综上所述,我认为while循环的优点是代码整洁和编写代码的速度(不一定是执行速度,尽管计算机如此强大,但人们不会注意到.)

我的上述假设是否正确?

编辑:很快,我看到一些答案证实了我对优化的初步想法。谢谢

以上代码示例与我的项目无关,仅供理解。

如有疑问:测量。

什么比较好?

  • 更少的字节码? ==> import dis 并比较字节码
  • 执行速度更快 ==> import timeit 比较 运行 倍
  • 可读性 ==> 取决于您最弱的同事理解您的代码的能力(运行 代码为 import this² 的文件;o)

像这样:

import dis
import timeit

def a():
    count = 0
    p = print  # local caching of global lookup - way faster
    while count < 10:
        p('hello', flush=True)
        count += 1

def b():
    p = print  # local caching of global lookup - way faster
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)
    p('hello', flush=True)

def c():
    print( *("hello" for _ in range(10)), sep="\n", flush=True)

aa = timeit.timeit(a, number=100)
bb = timeit.timeit(b, number=100)
cc = timeit.timeit(c, number=100)
print(aa, bb, cc, sep="\n")

dis.dis(a)
print("-"*80)
dis.dis(b)
print("-"*80)
dis.dis(c)

获得

0.059448799999699986  # while is faster - who would have thought
0.06415420000030281   # multiple prints
0.06454990000020189   # one print but list comp

# while loop  - seems to be shortest
  5           0 LOAD_CONST               1 (0)
              2 STORE_FAST               0 (count)

  6           4 LOAD_GLOBAL              0 (print)
              6 STORE_FAST               1 (p)

  7           8 LOAD_FAST                0 (count)
             10 LOAD_CONST               2 (10)
             12 COMPARE_OP               0 (<)
             14 POP_JUMP_IF_FALSE       24 (to 48)

  8     >>   16 LOAD_FAST                1 (p)
             18 LOAD_CONST               3 ('hello')
             20 LOAD_CONST               4 (True)
             22 LOAD_CONST               5 (('flush',))
             24 CALL_FUNCTION_KW         2
             26 POP_TOP

  9          28 LOAD_FAST                0 (count)
             30 LOAD_CONST               6 (1)
             32 INPLACE_ADD
             34 STORE_FAST               0 (count)

  7          36 LOAD_FAST                0 (count)
             38 LOAD_CONST               2 (10)
             40 COMPARE_OP               0 (<)
             42 POP_JUMP_IF_TRUE         8 (to 16)
             44 LOAD_CONST               0 (None)
             46 RETURN_VALUE
        >>   48 LOAD_CONST               0 (None)
             50 RETURN_VALUE
--------------------------------------------------------------------------------
# multiple prints
 11           0 LOAD_GLOBAL              0 (print)
              2 STORE_FAST               0 (p)

 12           4 LOAD_FAST                0 (p)
              6 LOAD_CONST               1 ('hello')
              8 LOAD_CONST               2 (True)
             10 LOAD_CONST               3 (('flush',))
             12 CALL_FUNCTION_KW         2
             14 POP_TOP

 13          16 LOAD_FAST                0 (p)
             18 LOAD_CONST               1 ('hello')
             20 LOAD_CONST               2 (True)
             22 LOAD_CONST               3 (('flush',))
             24 CALL_FUNCTION_KW         2
             26 POP_TOP

 14          28 LOAD_FAST                0 (p)
             30 LOAD_CONST               1 ('hello')
             32 LOAD_CONST               2 (True)
             34 LOAD_CONST               3 (('flush',))
             36 CALL_FUNCTION_KW         2
             38 POP_TOP

 15          40 LOAD_FAST                0 (p)
             42 LOAD_CONST               1 ('hello')
             44 LOAD_CONST               2 (True)
             46 LOAD_CONST               3 (('flush',))
             48 CALL_FUNCTION_KW         2
             50 POP_TOP

 16          52 LOAD_FAST                0 (p)
             54 LOAD_CONST               1 ('hello')
             56 LOAD_CONST               2 (True)
             58 LOAD_CONST               3 (('flush',))
             60 CALL_FUNCTION_KW         2
             62 POP_TOP

 17          64 LOAD_FAST                0 (p)
             66 LOAD_CONST               1 ('hello')
             68 LOAD_CONST               2 (True)
             70 LOAD_CONST               3 (('flush',))
             72 CALL_FUNCTION_KW         2
             74 POP_TOP

 18          76 LOAD_FAST                0 (p)
             78 LOAD_CONST               1 ('hello')
             80 LOAD_CONST               2 (True)
             82 LOAD_CONST               3 (('flush',))
             84 CALL_FUNCTION_KW         2
             86 POP_TOP

 19          88 LOAD_FAST                0 (p)
             90 LOAD_CONST               1 ('hello')
             92 LOAD_CONST               2 (True)
             94 LOAD_CONST               3 (('flush',))
             96 CALL_FUNCTION_KW         2
             98 POP_TOP

 20         100 LOAD_FAST                0 (p)
            102 LOAD_CONST               1 ('hello')
            104 LOAD_CONST               2 (True)
            106 LOAD_CONST               3 (('flush',))
            108 CALL_FUNCTION_KW         2
            110 POP_TOP

 21         112 LOAD_FAST                0 (p)
            114 LOAD_CONST               1 ('hello')
            116 LOAD_CONST               2 (True)
            118 LOAD_CONST               3 (('flush',))
            120 CALL_FUNCTION_KW         2
            122 POP_TOP
            124 LOAD_CONST               0 (None)
            126 RETURN_VALUE
--------------------------------------------------------------------------------

# fancy generator comprehension
 24           0 LOAD_GLOBAL              0 (print)
              2 LOAD_CONST               1 (<code object <genexpr> at 0x000002320A8468C0, file "c:\Users\partner\Documents\Coding\python\t.py", line 24>)
              4 LOAD_CONST               2 ('c.<locals>.<genexpr>')
              6 MAKE_FUNCTION            0
              8 LOAD_GLOBAL              1 (range)
             10 LOAD_CONST               3 (10)
             12 CALL_FUNCTION            1
             14 GET_ITER
             16 CALL_FUNCTION            1
             18 LOAD_CONST               4 ('\n')
             20 LOAD_CONST               5 (True)
             22 LOAD_CONST               6 (('sep', 'flush'))
             24 BUILD_CONST_KEY_MAP      2
             26 CALL_FUNCTION_EX         1
             28 POP_TOP
             30 LOAD_CONST               0 (None)
             32 RETURN_VALUE

Disassembly of <code object <genexpr> at 0x000002320A8468C0, file "c:\Users\partner\Documents\Coding\python\t.py", line 24>:
              0 GEN_START                0

 24           2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                 5 (to 16)
              6 STORE_FAST               1 (_)
              8 LOAD_CONST               0 ('hello')
             10 YIELD_VALUE
             12 POP_TOP
             14 JUMP_ABSOLUTE            2 (to 4)
        >>   16 LOAD_CONST               1 (None)
             18 RETURN_VALUE

¹) 由罗伯特·A·海因莱因 (Robert A. Heinlein) 在他的科幻小说 异国他乡 source 中创造。

²) The Zen of Python