Заинтриговал этот вопрос о бесконечных циклах в perl: while (1) Vs. for (;;) Есть ли разница в скорости? , Я решил провести подобное сравнение на python. Я ожидал, что компилятор сгенерирует тот же байт-код для while(True): pass
и while(1): pass
, но на самом деле это не так в python2.7.
Следующий сценарий:
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
заметно сложнее. Почему это?
В других контекстах python действует так, как если бы он 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 изменения в способе оценки логических значений?
Ответы:
В Python 2.x
True
это не ключевое слово, а просто встроенная глобальная константа , для которойbool
тип определен как 1 . Следовательно, интерпретатору по-прежнему необходимо загружать содержимоеTrue
. Другими словами,True
можно переназначить:В Python 3.x это действительно становится ключевым словом и настоящей константой:
таким образом интерпретатор может заменить
while True:
цикл бесконечным циклом.источник
while 1
иwhile True
они идентичны в Python 3?Это не совсем так,
поскольку еще можно вырваться из петли. Но верно, что такое предложение цикла
else
никогда не будет доступно в Python 3. И также верно, что упрощение поиска значения заставляет его работать так же быстро, какwhile 1
в Python 2.Сравнение производительности
Демонстрация разницы во времени для несколько нетривиального цикла while:
Настроить
Python 2
Python 3
объяснение
Чтобы объяснить разницу в Python 2:
но в Python 3:
Поскольку
True
это ключевое слово в Python 3, интерпретатору не нужно искать значение, чтобы увидеть, заменил ли его кто-то другим значением. Но поскольку одно значение можно присвоитьTrue
другому, интерпретатору приходится каждый раз его искать.Заключение для Python 2
Если у вас в Python 2 сложный и продолжительный цикл, вам, вероятно, следует использовать
while 1:
вместоwhile True:
.Заключение для Python 3
Используйте,
while True:
если у вас нет условий для выхода из цикла.источник
Это вопрос семилетней давности, на который уже есть отличный ответ, но неправильное представление о вопросе, которое не рассматривается ни в одном из ответов, делает его потенциально запутанным для некоторых других вопросов, отмеченных как повторяющиеся.
На самом деле
while
здесь вообще ничего не делается. Это отличает1
иTrue
точно таким же образом , что+
пример делает.Вот 2.7:
Теперь сравните:
Он генерирует a
LOAD_GLOBAL (True)
для каждогоTrue
, и оптимизатор ничего не может сделать с global. Итак,while
отличает1
иTrue
по той же причине, что+
и. (И==
не различает их, потому что оптимизатор не оптимизирует сравнения.)Теперь сравните 3.6:
Здесь он генерирует
LOAD_CONST (True)
для ключевого слова, чем может воспользоваться оптимизатор . Итак,True + 1
не различает по той же причинеwhile True
. (И==
все равно не различает их, потому что оптимизатор не оптимизирует сравнения.)В том же время, если код не оптимизированные, интерпретатор заканчивает обработку
True
и1
точно так же во всех этих трех случаях.bool
является подклассомint
и наследует большинство его методов от негоint
иTrue
имеет внутреннее целочисленное значение 1. Итак, выполняете ли выwhile
тест (__bool__
в 3.x,__nonzero__
в 2.x), сравнение (__eq__
) или арифметические операции. (__add__
), вы вызываете один и тот же метод независимо от того, используете ли выTrue
или1
.источник