Циклы Python "while" (неопределенная итерация)

Циклы Python "while" (неопределенная итерация)

Iteration означает выполнение одного и того же блока кода снова и снова, потенциально много раз. Программная структура, реализующая итерацию, называетсяloop.

В программировании существует два типа итераций: неопределенный и определенный:

  • Сindefinite iteration количество выполнений цикла не указывается заранее. Скорее, назначенный блок выполняется многократно, пока выполняется некоторое условие.

  • С помощьюdefinite iteration количество раз, которое будет выполняться назначенный блок, указывается явно в момент запуска цикла.

В этом уроке вы будете:

  • Узнайте о циклеwhile, управляющей структуре Python, используемой для неопределенной итерации

  • Посмотрите, как преждевременно вырваться из цикла или цикла итерации

  • Исследуйте бесконечные петли

Когда вы закончите, вы должны хорошо понимать, как использовать неопределенную итерацию в Python.

Free Bonus:Click here to get our free Python Cheat Sheet, который показывает вам основы Python 3, такие как работа с типами данных, словарями, списками и функциями Python.

__ Take the Quiz: Проверьте свои знания с помощью нашей интерактивной викторины «Python», пока «циклы». По окончании вы получите оценку, чтобы вы могли отслеживать прогресс в обучении с течением времени:

Циклwhile

Давайте посмотрим, как оператор Pythonwhile используется для построения циклов. Мы начнем с простого и украсим, как мы идем.

Формат рудиментарного циклаwhile показан ниже:

while :
    

<statement(s)> представляет блок, который будет повторно выполняться, часто называемый телом цикла. Это обозначается отступом, как в оператореif.

Remember: Все управляющие структуры в Python используют отступ для определения блоков. См. Обсуждениеgrouping statements в предыдущем руководстве.

Управляющее выражение<expr> обычно включает одну или несколько переменных, которые инициализируются перед запуском цикла, а затем изменяются где-то в теле цикла.

Когда встречается циклwhile, сначала вычисляется<expr> вBoolean context. Если это правда, тело цикла выполняется. Затем снова проверяется<expr>, и, если все еще верно, тело выполняется снова. Это продолжается до тех пор, пока<expr> не станет ложным, после чего выполнение программы перейдет к первому оператору за пределами тела цикла.

Рассмотрим этот цикл:

>>>

 1 >>> n = 5
 2 >>> while n > 0:
 3 ...     n -= 1
 4 ...     print(n)
 5 ...
 6 4
 7 3
 8 2
 9 1
10 0

Вот что происходит в этом примере:

  • n изначально равно5. Выражение в заголовке оператораwhile в строке 2 -n > 0, что верно, поэтому тело цикла выполняется. Внутри тела цикла в строке 3n уменьшается на1 до4, а затем печатается.

  • Когда тело цикла завершено, выполнение программы возвращается к началу цикла в строке 2, и выражение вычисляется снова. Это все еще верно, поэтому тело снова выполняется, и печатается3.

  • Это продолжается до тех пор, покаn не станет0. В этот момент, когда выражение проверяется, оно ложно, и цикл завершается. Выполнение возобновится с первого оператора, следующего за телом цикла, но в этом случае его нет.

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

>>>

>>> n = 0
>>> while n > 0:
...     n -= 1
...     print(n)
...

В приведенном выше примере, когда встречается цикл,n равно0. Управляющее выражениеn > 0 уже ложно, поэтому тело цикла никогда не выполняется.

Вот еще один циклwhile, в котором используется список, а не числовое сравнение:

>>>

>>> a = ['foo', 'bar', 'baz']
>>> while a:
...     print(a.pop(-1))
...
baz
bar
foo

Когдаlist is evaluated in Boolean context, он истинен, если в нем есть элементы, и ложен, если он пуст. В этом примереa истинно, пока в нем есть элементы. После того, как все элементы были удалены методом.pop() и список пуст,a принимает значение false, и цикл завершается.

Утверждения Pythonbreak иcontinue

В каждом из примеров, которые вы видели до сих пор, все тело циклаwhile выполняется на каждой итерации. Python предоставляет два ключевых слова, которые преждевременно завершают итерацию цикла:

  • Оператор Pythonbreak немедленно полностью завершает цикл. Выполнение программы продолжается до первого оператора, следующего за телом цикла.

  • Оператор Pythoncontinue немедленно завершает текущую итерацию цикла. Выполнение переходит на вершину цикла, и управляющее выражение переоценивается, чтобы определить, будет ли цикл выполняться снова или завершится.

Различие междуbreak иcontinue показано на следующей диаграмме:

Вот файл сценария с именемbreak.py, который демонстрирует операторbreak:

 1 n = 5
 2 while n > 0:
 3     n -= 1
 4     if n == 2:
 5         break
 6     print(n)
 7 print('Loop ended.')

Запускbreak.py из интерпретатора командной строки дает следующий вывод:

C:\Users\john\Documents>python break.py
4
3
Loop ended.

Когдаn становится2, выполняется инструкцияbreak. Цикл полностью завершается, и выполнение программы переходит к операторуprint() в строке 7.

Следующий сценарийcontinue.py идентичен, за исключением оператораcontinue вместоbreak:

 1 n = 5
 2 while n > 0:
 3     n -= 1
 4     if n == 2:
 5         continue
 6     print(n)
 7 print('Loop ended.')

Выводcontinue.py выглядит так:

C:\Users\john\Documents>python continue.py
4
3
1
0
Loop ended.

На этот раз, когдаn равно2, операторcontinue вызывает завершение этой итерации. Таким образом,2 не печатается. Выполнение возвращается к началу цикла, условие переоценивается, и оно все еще выполняется. Цикл возобновляется и завершается, когдаn становится0, как и раньше.

Пунктelse

Python допускает необязательное предложениеelse в конце циклаwhile. Это уникальная особенность Python, не встречающаяся в большинстве других языков программирования. Синтаксис показан ниже:

while :
    
else:
    

<additional_statement(s)>, указанный в предложенииelse, будет выполнен, когда циклwhile завершится.

thought balloon

Примерно сейчас вы можете подумать: «Чем это полезно?» Вы можете сделать то же самое, поместив эти операторы сразу после циклаwhile, безelse:

while :
    

Какая разница?

В последнем случае, без предложенияelse,<additional_statement(s)> будет выполняться после завершения циклаwhile, несмотря ни на что.

Когда<additional_statement(s)> помещается в предложениеelse, они будут выполняться только в том случае, если цикл завершится «исчерпанием», то есть, если цикл повторяется до тех пор, пока управляющее условие не станет ложным. Если цикл завершается операторомbreak, предложениеelse выполняться не будет.

Рассмотрим следующий пример:

>>>

>>> n = 5
>>> while n > 0:
...     n -= 1
...     print(n)
... else:
...     print('Loop done.')
...
4
3
2
1
0
Loop done.

В этом случае цикл повторяется до тех пор, пока условие не будет исчерпано:n стало0, поэтомуn > 0 стало ложным. Поскольку цикл дожил, так сказать, свою естественную жизнь, было выполнено предложениеelse. Теперь обратите внимание на разницу здесь:

>>>

>>> n = 5
>>> while n > 0:
...     n -= 1
...     print(n)
...     if n == 2:
...         break
... else:
...     print('Loop done.')
...
4
3
2

Этот цикл прерывается преждевременно сbreak, поэтому предложениеelse не выполняется.

Может показаться, что значение словаelse не совсем соответствует циклуwhile так же, как оно подходит для оператораif. Guido van Rossum, создатель Python, на самом деле сказал, что, если бы ему пришлось делать это снова, он бы оставил предложениеelse циклаwhile вне языка.

Одна из следующих интерпретаций может помочь сделать ее более интуитивной:

  • Подумайте о заголовке цикла (while n > 0) как об оператореif (if n > 0), который выполняется снова и снова, причем предложениеelse, наконец, выполняется, когда условие становится ложным.

  • Думайте оelse как оnobreak, поскольку следующий за ним блок выполняется, если не былоbreak.

Если вы не находите ни одну из этих интерпретаций полезной, не стесняйтесь игнорировать их.

Когда может быть полезно предложениеelse в циклеwhile? Одна общая ситуация, если вы ищете в списке определенный элемент. Вы можете использоватьbreak для выхода из цикла, если элемент найден, а предложениеelse может содержать код, который предназначен для выполнения, если элемент не найден:

>>>

>>> a = ['foo', 'bar', 'baz', 'qux']
>>> s = 'corge'

>>> i = 0
>>> while i < len(a):
...     if a[i] == s:
...         # Processing for item found
...         break
...     i += 1
... else:
...     # Processing for item not found
...     print(s, 'not found in list.')
...
corge not found in list.

Note: Код, показанный выше, полезен для иллюстрации концепции, но на самом деле вы вряд ли будете искать в списке таким образом.

Во-первых, списки обычно обрабатываются с определенной итерацией, а не с цикломwhile. Определенная итерация рассматривается в следующем уроке этой серии.

Во-вторых, Python предоставляет встроенные способы поиска элемента в списке. Вы можете использовать операторin:

>>>

>>> if s in a:
...     print(s, 'found in list.')
... else:
...     print(s, 'not found in list.')
...
corge not found in list.

Также подойдет методlist.index(). Этот метод вызывает исключениеValueError, если элемент не найден в списке, поэтому вам необходимо понимать обработку исключений, чтобы его использовать. В Python вы используете операторtry для обработки исключения. Пример приведен ниже:

>>>

>>> try:
...     print(a.index('corge'))
... except ValueError:
...     print(s, 'not found in list.')
...
corge not found in list.

Вы узнаете об обработке исключений позже в этой серии.

Предложениеelse с цикломwhile - это немного странность, которую не часто можно увидеть. Но не стесняйтесь, если вы обнаружите ситуацию, в которой вы чувствуете, что это добавляет ясности вашему коду!

Бесконечные циклы

Предположим, вы пишете циклwhile, который теоретически никогда не заканчивается. Звучит странно, правда?

Рассмотрим этот пример:

>>>

>>> while True:
...     print('foo')
...
foo
foo
foo
  .
  .
  .
foo
foo
foo
KeyboardInterrupt
Traceback (most recent call last):
  File "", line 2, in 
    print('foo')

Этот код завершился [.keys] #Ctrl [.kbd .key-c] # C ##, который генерирует прерывание с клавиатуры. Иначе это продолжалось бы бесконечно. Многие выходные строки `+ foo` были удалены и заменены вертикальным многоточием в показанном выходе.

Ясно, чтоTrue никогда не будет ложным, иначе у всех нас будут большие проблемы. Таким образом,while True: запускает бесконечный цикл, который теоретически будет работать вечно.

Возможно, это не похоже на то, что вы хотели бы сделать, но этот паттерн на самом деле довольно распространен. Например, вы можете написать код для службы, которая запускается и работает навсегда, принимая запросы на обслуживание. «Вечно» в этом контексте означает, пока вы не отключите его или пока не наступит тепловая смерть вселенной, в зависимости от того, что наступит раньше.

Более прозаично, помните, что цикл может быть разорван с помощью оператораbreak. Может быть более простым завершить цикл на основе условий, распознанных в теле цикла, а не на условии, оцененном сверху.

Вот еще один вариант цикла, показанный выше, который последовательно удаляет элементы из списка с помощью.pop(), пока он не станет пустым:

>>>

>>> a = ['foo', 'bar', 'baz']
>>> while True:
...     if not a:
...         break
...     print(a.pop(-1))
...
baz
bar
foo

Когдаa становится пустым,not a становится истинным, и операторbreak выходит из цикла.

Вы также можете указать несколько операторовbreak в цикле:

while True:
    if :  # One condition for loop termination
        break
    ...
    if :  # Another termination condition
        break
    ...
    if :  # Yet another
        break

В подобных случаях, когда есть несколько причин для завершения цикла, часто лучше использоватьbreak из нескольких разных мест, чем пытаться указать все условия завершения в заголовке цикла.

Бесконечные циклы могут быть очень полезны. Просто помните, что вы должны убедиться, что цикл в какой-то момент разорван, чтобы он действительно не становился бесконечным.

Вложенные циклыwhile

В общем, управляющие структуры Python могут быть вложены друг в друга. Например, условные операторыif /elif /else могут быть вложенными:

if age < 18:
    if gender == 'M':
        print('son')
    else:
        print('daughter')
elif age >= 18 and age < 65:
    if gender == 'M':
        print('father')
    else:
        print('mother')
else:
    if gender == 'M':
        print('grandfather')
    else:
        print('grandmother')

Точно так же циклwhile может содержаться в другом циклеwhile, как показано здесь:

>>>

>>> a = ['foo', 'bar']
>>> while len(a):
...     print(a.pop(0))
...     b = ['baz', 'qux']
...     while len(b):
...         print('>', b.pop(0))
...
foo
> baz
> qux
bar
> baz
> qux

Операторbreak илиcontinue, найденный во вложенных циклах, применяется к ближайшему охватывающему циклу:

while :
    statement
    statement

    while :
        statement
        statement
        break  # Applies to while : loop

    break  # Applies to while : loop

Кроме того, циклыwhile могут быть вложены в инструкцииif /elif /else, и наоборот:

if :
    statement
    while :
        statement
        statement
else:
    while :
        statement
        statement
    statement
while :
    if :
        statement
    elif :
        statement
    else:
        statement

    if :
        statement

Фактически, все управляющие структуры Python могут смешиваться друг с другом в любой степени, в которой вы нуждаетесь. Так и должно быть. Представьте, как было бы неприятно, если бы возникли неожиданные ограничения, такие как «Цикл Awhile не может содержаться внутри оператораif» или «Циклыwhile могут быть вложены друг в друга только на глубина всего четыре ". Вам будет очень сложно их все запомнить.

Казалось бы, произвольные числовые или логические ограничения считаются признаком плохого дизайна программного языка. К счастью, вы не найдете много в Python.

Однострочные циклыwhile

Как и в случае с операторомif, циклwhile может быть указан в одной строке. Если в блоке, составляющем тело цикла, есть несколько операторов, их можно разделить точкой с запятой (;):

>>>

>>> n = 5
>>> while n > 0: n -= 1; print(n)

4
3
2
1
0

Это работает только с простыми утверждениями, хотя. Вы не можете объединить два составных оператора в одну строку. Таким образом, вы можете указать циклwhile в одной строке, как указано выше, и написать операторif в одной строке:

>>>

>>> if True: print('foo')

foo

Но вы не можете сделать это:

>>>

>>> while n > 0: n -= 1; if True: print('foo')
SyntaxError: invalid syntax

Помните, чтоPEP 8 не рекомендует использовать несколько операторов в одной строке. Так что вы, вероятно, не должны делать что-то очень часто, во всяком случае.

Заключение

В этом руководстве вы узнали оindefinite iteration с помощью цикла Pythonwhile. Теперь вы можете:

  • Построить базовый и сложныйwhile петли

  • Выполнение цикла прерывания сbreak иcontinue

  • Используйте предложениеelse с цикломwhile

  • Разобраться с бесконечными петлями

Теперь вы должны хорошо понимать, как выполнять фрагмент кода повторно.

__ Take the Quiz: Проверьте свои знания с помощью нашей интерактивной викторины «Python», пока «циклы». По окончании вы получите оценку, чтобы вы могли отслеживать прогресс в обучении с течением времени:

В следующем учебном пособии этой серии рассматриваетсяdefinite iteration с цикламиfor - повторяющееся выполнение, в котором количество повторений указывается явно.