Есть ли какой-либо случай в Python, когда использование цикла while будет лучшей практикой? - PullRequest
4 голосов
/ 15 января 2012

Я провожу некоторые тесты Python и обнаружил, что repeat(None) намного быстрее, чем while True или while 1:

>>> def bench7():
...   foo = 0
...   a = time()
...   for i in repeat(None):
...     foo += 1
...     if foo == 100000000:
...       break
...   b = time()
...   print a, b, b-a
... 
>>> def bench8():
...   foo = 0
...   a = time()
...   while True:
...     foo += 1
...     if foo == 100000000:
...       break
...   b = time()
...   print a, b, b-a
... 
>>> bench7()
1326592924.41 1326592935.42 11.0051281452
>>> bench7()
1326592936.36 1326592947.48 11.1183578968
>>> bench8()
1326592951.47 1326592965.03 13.5640599728
>>> bench8()
1326592966.07 1326592979.6 13.5341670513`

Такого рода использование цикла while было последним, что я использовал для циклов while. Есть ли какая-либо причина, по которой я могу пропустить, пока я пропускаю?

Ответы [ 3 ]

8 голосов
/ 15 января 2012

while True медленнее только из-за глобального поиска для True. Если вместо этого вы используете while 1, цикл while должен легко превзойти повтор (хотя бы с точки зрения скорости, красоты и ясности):

>>> from dis import dis
>>> def f():
        while True:
            print

>>> dis(f)
  2           0 SETUP_LOOP              11 (to 14)
        >>    3 LOAD_GLOBAL              0 (True)
              6 POP_JUMP_IF_FALSE       13
  3           9 PRINT_NEWLINE       
             10 JUMP_ABSOLUTE            3
        >>   13 POP_BLOCK           
        >>   14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        

>>> def g():
        while 1:
            print

>>> dis(g)
  2           0 SETUP_LOOP               4 (to 7)
  3     >>    3 PRINT_NEWLINE       
              4 JUMP_ABSOLUTE            3
        >>    7 LOAD_CONST               0 (None)
             10 RETURN_VALUE    

Основной вариант использования для repeat заключается в предоставлении потока постоянных значений для imap или izip . Например, следующее вычисляет сумму степеней двух: sum(imap(pow, repeat(2), xrange(10))).

itertool repeat также можно использовать для ускорения цикла for, для которого не требуется изменение переменной. Например, Гвидо использовал эту технику, чтобы минимизировать количество циклов в модуле timeit : http://hg.python.org/cpython/file/40e1be1e0707/Lib/timeit.py#l188

Чтобы ответить на ваш другой вопрос, "есть ли причины использовать цикл while". Ответ - да. Цикл for в Python - это действительно foreach, который использует итераторы для создания потока значений. В отличие от этого, цикл while либо не ограничен (как в примере while-True), либо завершается, когда выполняется определенное условие (например, циклическое выполнение пользовательских вводов до тех пор, пока пользователь не введет «выход» или что-то подобное).

Контрастирующие возможности циклов while и for-loop можно увидеть на примере гипотезы Коллатца , где цикл while нельзя легко заменить на цикл for:

def collatz(n):
    print n
    while n > 1:
        n = n // 2 if n % 2 == 0 else n * 3 + 1
        print n

Многие другие примеры и варианты использования для циклов while можно увидеть, выполнив поиск по Стандартная библиотека Python .

Таким образом, оператор while является неотъемлемой частью вашего инструментария: -)

1 голос
/ 15 января 2012

В то время как циклы позволяют проверять истинность значения.

while x < y:

Возможно, поэтому оно медленнее, чем повтор?

0 голосов
/ 15 января 2012

repeat(None) быстрее, чем while True, но не while 1, потому что while True запускает поиск по глобальной переменной True. while 1 примерно на 14% быстрее, чем repeat(None).

...