Я видел два способа создания бесконечного цикла в Python:
while 1: do_something()
while True: do_something()
Есть ли разница между ними? Является ли один более питоническим, чем другой?
Я видел два способа создания бесконечного цикла в Python:
while 1:
do_something()
while True:
do_something()
Есть ли разница между ними? Является ли один более питоническим, чем другой?
Принципиально это не имеет значения, такие мелочи на самом деле не влияют на то, является ли что-то «питоновским» или нет.
Однако, если вас интересуют мелочи, есть некоторые отличия.
встроенный логический тип не существовал до Python 2.3 поэтому код, предназначенный для запуска в старых версиях, имеет тенденцию использовать форму while 1:
. Например, вы увидите его в стандартной библиотеке.
Встроенные функции True и False — это не зарезервированные слова до Python 3 так можно было бы присвоить, изменив их значение. Это помогает в приведенном выше случае, потому что код может выполнять True = 1
для обратной совместимости, но это означает, что имя True
нужно искать в словаре глобальных переменных каждый раз, когда оно используется.
Из-за вышеуказанного ограничения байт-код, в который компилируются две версии, отличается в Python 2, поскольку существует оптимизация для постоянных целых чисел, которую он не может использовать для True
. Поскольку при компиляции 1
Python может сказать, что он всегда не равен нулю, он удаляет условный переход и вообще не загружает константу:
>>> import dis
>>> def while_1():
... while 1:
... pass
...
>>> def while_true():
... while True:
... pass
...
>>> dis.dis(while_1)
2 0 SETUP_LOOP 5 (to 8)
3 >> 3 JUMP_ABSOLUTE 3
6 POP_TOP
7 POP_BLOCK
>> 8 LOAD_CONST 0 (None)
11 RETURN_VALUE
>>> dis.dis(while_true)
2 0 SETUP_LOOP 12 (to 15)
>> 3 LOAD_GLOBAL 0 (True)
6 JUMP_IF_FALSE 4 (to 13)
9 POP_TOP
3 10 JUMP_ABSOLUTE 3
>> 13 POP_TOP
14 POP_BLOCK
>> 15 LOAD_CONST 0 (None)
18 RETURN_VALUE
Итак, while True:
немного легче читать, а while 1:
немного добрее к старым версиям Python. Поскольку в наши дни вам вряд ли понадобится работать на Python 2.2 или беспокоиться о подсчете байт-кода ваших циклов, первое предпочтительнее.
while True:
более питонический. По крайней мере, как я интерпретирую странный термин pythonic, ваш пробег может отличаться.
- person porgarmingduod; 15.02.2010
True = False
, работает как положено, забавно :)
- person Antonio; 11.09.2013
True
в 3.x, если очень постараетесь. В версии 3.0 это сделает import builtins; builtins.__dict__['True'] = 0
; в 3.3 вам нужно проявить гораздо больше творчества, но это все еще возможно. В худшем случае вы всегда можете ctypes
перейти к C API (или эквиваленту для других реализаций). Самое интересное, что компилятор предполагает, что вы не можете этого сделать, поэтому некоторые выражения будут скомпилированы, а другие будут использовать ваше новое значение в зависимости от реализации/версии. И если вы сможете найти всему этому хорошее применение… вы, вероятно, сможете найти и лучшие способы использовать свое время…
- person abarnert; 16.09.2013
Самый питонический способ всегда будет самым читаемым. Используйте 1_
Это действительно не имеет значения. Ни то, ни другое не сложно прочитать или понять, хотя лично я всегда использовал бы while True
, что немного более явно.
В более общем смысле, многие циклы while-break, которые люди пишут на Python, могут быть чем-то другим. Иногда я вижу, как люди пишут i = 0; while True: i += 1 ...
, которое можно заменить на for i in itertools.count()
, и люди пишут while True: foo = fun() if foo is None: break
, когда можно написать for foo in iter(fun, None)
, что требует обучения, но имеет меньше шаблонов и возможностей для глупых ошибок.
Ни один.
Оба они означают, что я должен сканировать код в поисках break
вместо того, чтобы увидеть условие остановки прямо там, где оно должно быть.
Я стараюсь избегать подобных вещей везде, где это возможно, а если это невозможно, пусть код говорит сам за себя:
while not found_answer:
check_number += 1
if check_number == 42:
found_answer = True
Редактировать: кажется, что слово "избегать" выше было недостаточно ясным. Использование практически бесконечного цикла и выход из него где-то внутри цикла (используя break
) обычно следует вообще избегать. Иногда это невозможно. В этом случае мне нравится использовать что-то вроде приведенного выше кода, который, тем не менее, по-прежнему представляет ту же концепцию приведенный выше код является не более чем компромиссом, но, по крайней мере, Я могу показать назначение цикла в начале так же, как не вызывал бы функцию do_something_with_args(*args)
.
found_answer = True
.
- person Mike Graham; 14.02.2010
break
является то, что условие остановки не может быть легко или эффективно выражено. Если вы буквально имеете в виду использование такой переменной, как found_answer
, тогда вам нужно сканировать ее, а не break
, и, как правило, вам все равно понадобится continue
вместо break
, чтобы выйти из цикла.
- person Scott Griffiths; 14.02.2010
True
, not found_answer
или not received_quit_command
что-то сообщает читателю кода.
- person balpha; 14.02.2010
ИМО, второй вариант более очевиден.
Если бы вы могли избавиться от while
и написать более компактный код, это могло бы быть более питоническим.
Например:
# Get the even numbers in the range 1..10
# Version 1
l = []
n = 1
while 1:
if n % 2 == 0: l.append(n)
n += 1
if n > 10: break
print l
# Version 2
print [i for i in range(1, 11) if i % 2 == 0]
# Version 3
print range(2, 11, 2)
Я думаю, что это в основном вопрос стиля. Оба должны быть легко поняты как бесконечный цикл.
Однако лично я предпочитаю второй вариант. Это потому, что для понимания требуется всего один умственный микрошаг, особенно для программистов без опыта работы с C.
Первый будет работать и в тех ранних версиях, где True
еще не определен.
Если у вас есть алгоритм, который должен завершаться за конечное время, я бы рекомендовал это, что всегда безопаснее, чем while True
:
maxiter = 1000
for i in xrange(maxiter):
# your code
# on success:
break
else:
# that algorithm has not finished in maxiter steps! do something accordingly
Я считаю, что второе выражение является более явным и, следовательно, более pythonic а>.
Это лишь вопрос стиля, любой новичок в программировании поймет любой вариант.
Но второй вариант будет работать только в том случае, если True
не был назначен False
, что было возможно до Python 3:
>>> True = False
>>> True
False
Лучший способ - "пока правда" с условным выходом из цикла.