Я видел два способа создать бесконечный цикл в Python:
while 1:
do_something()
while True:
do_something()
Есть ли какое-либо различие между ними? Еще один pythonic, чем другой?
По сути, это не имеет значения, такие мелочи не влияют на то, является ли что-то «питоническим» или нет.
Если вас интересуют мелочи, есть некоторые отличия.
Встроенный логический тип не существовал до Python 2.3 , поэтому код, предназначенный для работы в старых версиях, как правило, использует форму и 1:
. Вы увидите это, например, в стандартной библиотеке.
Встроенные команды True и False - это незарезервированные слова до Python 3 , поэтому их можно было присвоить, изменив их значение. Это помогает в приведенном выше случае, потому что код может сделать True = 1
для обратной совместимости, но означает, что имя True
необходимо искать в словаре глобальных переменных каждый раз, когда оно используется.
Из-за вышеуказанного ограничения байт-код, в который компилируются две версии, отличается в Python 2, поскольку существует оптимизация для постоянных целых чисел, которую нельзя использовать для True
. Поскольку Python при компиляции 1
может сказать, что оно всегда не равно нулю, он удаляет условный переход и вообще не загружает константу:
>>> import dis
> >> def while_1 ():
... while 1:
... pass
...
>>> def while_true (): {{ 1}} ... while True:
... pass
...
>>> dis.dis (while_1)
2 0 SETUP_LOOP 5 ( на 8)
3 >> 3 JUMP_ABSOLUTE 3
6 POP_TOP
7 POP_BLOCK
>> 8 LOAD_CONST 0 (Нет) {{1} } 11 RETURN_VALUE
>>> дис.dis (while_true)
2 0 SETUP_LOOP 12 (до 15)
>> 3 LOAD_GLOBAL 0 (True)
6 JUMP_IF_FALSE 4 (до 13)
9 POP_TOP { {1}}
3 10 JUMP_ABSOLUTE 3
>> 13 POP_TOP
14 POP_BLOCK
>> 15 LOAD_CONST 0 (Нет)
18 RETURN_VALUE { {1}}
Итак, while True:
немного легче читать, а while 1:
немного лучше старых версий Python. Поскольку в наши дни вам вряд ли понадобится запускать Python 2.2 или нужно беспокоиться о счетчике байт-кода ваших циклов, первое предпочтительнее.
ИМО, второй вариант более очевиден .
Если бы вы могли избавиться от 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)
Ни то, ни другое.
Оба они означают, что я должен сканировать код в поисках разрыва
, вместо того, чтобы видеть условие остановки прямо там, где оно должно быть.
Я стараюсь избегать такого рода вещей везде, где это возможно, а если это невозможно, пусть код говорит сам за себя следующим образом:
while not found_answer:
check_number += 1
if check_number == 42:
found_answer = True
Изменить: Кажется, что слово «избегать» выше было непонятным достаточно. Обычно следует избегать использования практически бесконечного цикла и выхода из него где-то внутри цикла (с использованием break
) . Иногда это невозможно.В этом случае мне нравится использовать что-то вроде приведенного выше кода , который, однако, по-прежнему представляет ту же концепцию - приведенный выше код является не более чем компромиссом - но, по крайней мере, Я могу показать цель цикла в начале - точно так же, как я бы не стал вызывать функцию do_something_with_args (* args)
.
Это только вопрос стиля, любой новичок в программировании поймет любой вариант.
Но второй вариант будет работать, только если True
не было присвоено False
, что было возможно до Python 3:
>>> True = False
>>> True
False
Лично я предпочитаю Visual Studio Unit Testing Framework по двум основным причинам:
Сказав, что практически любая структура модульного тестирования сделает трюк, важно иметь тесты!
-121--872732-Из RGB целого числа:
Blue = RGBint mod 256
Green = RGBint / 256 mod 256
Red = RGBint / 256 / 256 mod 256
Это может быть довольно просто реализовано, как только вы знаете, как его получить.:)
Upd: Добавлена функция python. Не уверен, что есть лучший способ сделать это, но это работает на Python 3 и 2,4
def rgb_int2tuple(rgbint):
return (rgbint // 256 // 256 % 256, rgbint // 256 % 256, rgbint % 256)
Есть также отличное решение, которое использует битшифтинг и маскирование, что, несомненно, гораздо быстрее, что Нильс Пипенбринк опубликовал.
-121--2289740-Лучшим способом является «while 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
Самый питонический способ всегда будет наиболее читаемым. Используйте , пока True:
Это не имеет особого значения. Ни то, ни другое не сложно прочитать или понять, хотя лично я всегда использовал , а True
, что немного более ясно.
В общем, множество циклов while-break, которые люди пишут на Python, могут быть чем-то другим. Иногда я вижу, как люди пишут i = 0; while True: i + = 1 ...
, который можно заменить на для i в itertools.count ()
и люди пишут while True: foo = fun () если foo Нет: break
, когда это может быть написано для foo in iter (fun, None)
, что требует обучения, но имеет меньше шаблонов и возможность для глупых ошибок.
Я думаю, что это в основном вопрос стиля. Оба варианта должны быть легко понятны как бесконечный цикл.
Однако лично я предпочитаю второй вариант. Потому что для его понимания требуется на один микрошаг меньше умственных усилий, особенно для программистов без знания языка Си.
Первая будет работать также в тех ранних версиях, где True
еще не определен.
Я считаю второе выражение более явное и, следовательно, более питоническое .