В то время как (1) Vs. пока (правда). Почему разница?
Заинтригованный этим вопросом о бесконечных циклах в perl: while (1) Vs. for (;;) Есть ли разница в скорости?, я решил запустить аналогичное сравнение в python. Я ожидал, что компилятор будет генерировать один и тот же байтовый код для while(True): pass
и while(1): pass
, но на самом деле это не так в python2.7.
Следующий script:
import dis
def while_one():
while 1:
pass
def while_true():
while True:
pass
print("while 1")
print("----------------------------")
dis.dis(while_one)
print("while True")
print("----------------------------")
dis.dis(while_true)
дает следующие результаты:
while 1
----------------------------
4 0 SETUP_LOOP 3 (to 6)
5 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
while True
----------------------------
8 0 SETUP_LOOP 12 (to 15)
>> 3 LOAD_GLOBAL 0 (True)
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP
9 10 JUMP_ABSOLUTE 3
>> 13 POP_TOP
14 POP_BLOCK
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Использование while True
заметно сложнее. Почему это?
В других контекстах питон действует так, как будто True
равно 1:
>>> True == 1
True
>>> True + True
2
Почему while
отличает два?
Я заметил, что python3 оценивает операторы, используя идентичные операции:
while 1
----------------------------
4 0 SETUP_LOOP 3 (to 6)
5 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
while True
----------------------------
8 0 SETUP_LOOP 3 (to 6)
9 >> 3 JUMP_ABSOLUTE 3
>> 6 LOAD_CONST 0 (None)
9 RETURN_VALUE
Есть ли изменение в python3 на способ вычисления булевых элементов?
Ответы
Ответ 1
В Python 2.x True
не является ключевым словом, а просто встроенная глобальная константа, которая определена как 1 в тип bool
. Поэтому интерпретатору по-прежнему приходится загружать содержимое True
. Другими словами, True
переназначается:
Python 2.7 (r27:82508, Jul 3 2010, 21:12:11)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
>>> True
4
В Python 3.x он действительно становится ключевым словом и реальной константой:
Python 3.1.2 (r312:79147, Jul 19 2010, 21:03:37)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
File "<stdin>", line 1
SyntaxError: assignment to keyword
Таким образом, интерпретатор может заменить цикл while True:
на бесконечный цикл.
Ответ 2
Это не совсем правильно,
таким образом, интерпретатор может заменить while while: цикл с бесконечным циклом.
поскольку все еще может выйти из цикла. Но верно, что такое предложение цикла else
никогда не будет доступно в Python 3. И также верно, что упрощение поиска значения заставляет его работать так же быстро, как while 1
в Python 2.
Сравнение производительности
Демонстрируя разницу во времени для несколько нетривиального цикла while:
Настройка
def while1():
x = 0
while 1:
x += 1
if x == 10:
break
def whileTrue():
x = 0
while True:
x += 1
if x == 10:
break
Python 2
>>> import timeit
>>> min(timeit.repeat(while1))
0.49712109565734863
>>> min(timeit.repeat(whileTrue))
0.756627082824707
Python 3
>>> import timeit
>>> min(timeit.repeat(while1))
0.6462970309949014
>>> min(timeit.repeat(whileTrue))
0.6450748789939098
Объяснение
Чтобы объяснить разницу, в Python 2:
>>> import keyword
>>> 'True' in keyword.kwlist
False
но в Python 3:
>>> import keyword
>>> 'True' in keyword.kwlist
True
>>> True = 'true?'
File "<stdin>", line 1
SyntaxError: can't assign to keyword
Так как True
является ключевым словом в Python 3, интерпретатору не нужно искать значение, чтобы увидеть, заменил ли кто-нибудь его другое значение. Но поскольку для другого значения можно присваивать True
, интерпретатор должен каждый раз искать его.
Заключение для Python 2
Если у вас жесткий, длинный цикл в Python 2, вы, вероятно, должны использовать while 1:
вместо while True:
.
Заключение для Python 3
Используйте while True:
, если у вас нет условий для выхода из цикла.