В качестве преамбулы вы должны знать, что ваши "сравнения" должны анализироваться изолированно (а не сравниваться друг с другом), потому что
- Цикл for - это фиксированный итератор, который ничего не делает внутриего тело
- Циклы while выполняют декремент / приращение в своем теле, а
- Понимание списка - это больше, чем просто цикл
for
, и с этим я перехожу к ответу на вопрос #1.
# 1, потому что цикл for
повторяется.Понимание списка повторяется, и создает список в памяти.Это, конечно, способствует общему времени.Одного этого должно быть достаточно, чтобы убедить вас, но если это не так, взгляните на разобранный байт-код, чтобы увидеть, что делает каждый.Для этого вы можете использовать модуль dis
.Я на самом деле использую dis
, чтобы ответить на ваш третий вопрос.
# 2, поэтому я не могу воспроизвести на python3.6.
%%timeit
i = 0; n = 100000
while i < n: i += 1
11.5 ms ± 65.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
n = 100000
while n > 0: n -= 1
10.8 ms ± 380 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Как правило, цикл на основе декремента должен быть немного быстрее, потому что сравнение с 0 (n > 0
) обычно быстрее, чем сравнение с ненулевыми значениями (i < n
).Но дельта обычно «серьезно, не беспокойтесь об этом», вроде небольшая.
Чтобы ответить на вопрос № 3, нам нужно немного покопаться.Давайте посмотрим на байт-код.
import dis
python3.6
dis.dis(
'''n = 100000
while n > 0: n -= 1'''
)
1 0 LOAD_CONST 0 (100000)
2 STORE_NAME 0 (n)
2 4 SETUP_LOOP 20 (to 26)
>> 6 LOAD_NAME 0 (n)
8 LOAD_CONST 1 (0)
10 COMPARE_OP 4 (>)
12 POP_JUMP_IF_FALSE 24
14 LOAD_NAME 0 (n)
16 LOAD_CONST 2 (1)
18 INPLACE_SUBTRACT
20 STORE_NAME 0 (n)
22 JUMP_ABSOLUTE 6
>> 24 POP_BLOCK
>> 26 LOAD_CONST 3 (None)
28 RETURN_VALUE
python2.7
dis.dis(
'''n = 100000
while n > 0: n -= 1'''
)
0 JUMP_FORWARD 15648 (to 15651)
3 SLICE+2
4 <49>
5 <48>
6 <48>
7 <48>
8 <48>
9 <48>
10 UNARY_POSITIVE
11 CONTINUE_LOOP 26984
14 IMPORT_NAME 8293 (8293)
17 SLICE+2
18 JUMP_FORWARD 15904 (to 15925)
21 SLICE+2
22 <48>
23 INPLACE_DIVIDE
24 SLICE+2
25 JUMP_FORWARD 11552 (to 11580)
28 DELETE_SUBSCR
29 SLICE+2
30 <49>
Обратите внимание, что существуют огромные различия в сгенерированном байт-коде.Разница лежит здесь.