- KotazIO
- Цикл while
- Цикл for
- Общее понятие
- range()
- Словари
- Оператор continue
- Оператор break
- Волшебное слово else
- Искусство написания циклов на Python
- Одновременно получаем значения и индексы
- Как избежать вложенных циклов с помощью функции Product
- Используем модуль Itertools для написания красивых циклов
- Создаём бесконечный цикл
- Комбинируем несколько итераторов в один
- Выделяем соседние дублирующиеся элементы
- Самостоятельно настраиваем цикл
- Вывод
- На правах рекламы
KotazIO
Я расскажу о циклах for и while, операторах break и continue, а также о слове else, которое, будучи употребленное с циклом, может сделать программный код несколько более понятным.
Цикл while
While — один из самых универсальных циклов в Python, поэтому довольно медленный. Выполняет тело цикла до тех пор, пока условие цикла истинно.
>>> i = 5 >>> while i 15: . print(i) . i = i + 2 . 5 7 9 11 13
Цикл for
Общее понятие
Цикл for уже чуточку сложнее, чуть менее универсальный, но выполняется гораздо быстрее цикла while. Этот цикл проходится по любому итерируемому объекту (например строке или списку), и во время каждого прохода выполняет тело цикла. Цикл for используется в том случае, когда необходимо выполнить некоторую часть кода до тех пор, пока не будет выполнено заданное условие. Цикл for также называют циклом c предусловием. Лучше использовать цикл for, если количество итераций известно заранее.
>>> >>> for i in 'hello world': . print(i * 2, end='') . hheelllloo wwoorrlldd
range()
Мы используем встроенную функцию Python range. Функция range создаст список длинной в «n» элементов. В Python версии 2.Х существует другая функция под названием xrange, которая является генератором чисел и не такая ресурсоемкая, как range. Ранее разработчики сменили xrange на range в Python 3. Вот пример:
print(range(5)) # ответ: range(0, 5)
Как вы видите, функция range взяла целое число и вернула объект range. Функция range также принимает начальное значение, конечное значение и значение шага. Вот еще два примера:
a = range(5, 10) print(a) # range(5, 10) b = list(range(1, 10, 2)) print(b) # [1, 3, 5, 7, 9]
В пером примере показано, что вы можете передать начальное и конечное значение, и функция range вернет числа, начиная с начального значения вплоть до (но не включая) последнее значение. Например, при запросе 5-10 мы получим 5-9. Во втором примере видно, как использовать функцию списка (list) для того, чтобы функция range вернула каждый второй элемент, между 1 и 10. Так что она начинает с 1, пропускает 2 и так далее. Теперь вы, наверное, гадаете, что же именно она будет делать с циклами? Что-ж, есть один простой способ показать, как работает цикл с использованием функции range! Давайте взглянем:
for number in range(5): print(number)
Что здесь произошло? Давайте почитаем слева на право, чтобы понять это. Для каждого числа в диапазоне 5 мы вводим число. Мы знаем, что если мы вызываем range со значением 5, мы получим список из 5 элементов. Так что каждый раз, проходя через цикл, она выводит каждый из элементов. Цикл for, показанный выше, может быть эквивалентом следующего:
for number in [0, 1, 2, 3, 4]: print(number)
Мы попробуем применить цикл в функции range, но нам нужно вывести только целые числа. Чтобы сделать это, нам нужно использовать условный оператор вместо параметра шага range. Это можно сделать следующим образом:
for number in range(10): if number % 2 == 0: print(number) # 0 # 2 # 4 # 6 # 8
Вы наверное гадаете, что вообще здесь происходит? Что еще за знак процента? В Python, % называется оператором модуля. Когда вы используете оператор модуля, он возвращает остаток. Когда вы делите целое число на два, вы получаете число без остатка, так что мы выводим эти числа. Вам, возможно, не захочется использовать оператор модуля часто в будущем, но в моей работе он нередко помогает. Теперь мы можем взглянуть на цикл while.
Словари
Функция range лишь делает результат несколько меньшим. Цикл for может обходить любой итератор Python. Мы уже видели, как именно он может работать со списком. Давайте взглянем, может ли он выполнять итерацию со словарем.
a_dict = "one":1, "two":2, "three":3> for key in a_dict: print(key)
Когда вы используете for в словаре, вы увидите, что он автоматически перебирает ключи. Вам не нужно указывать ключ for в a_dict.keys() (впрочем, это также работает). Python делает только нужные нам вещи. Вы возможно думаете, почему ключи выводятся в другом порядке, отличном от того, какой был указан в словаре? Как мы знаем из соответствующей статьи, словари не упорядочены, так что мы можем выполнять итерацию над ними, при этом ключи могут быть в любом порядке. Теперь, зная, что ключи могут быть отсортированы, вы можете отсортировать их до итерации. Давайте немного изменим словарь, чтобы увидеть, как это работает.
a_dict = 1:"one", 2:"two", 3:"three"> keys = a_dict.keys() keys = sorted(keys) for key in keys: print(key) # 1 # 2 # 3
Давайте остановимся и разберемся с тем, что делает этот код. Во-первых, мы создали словарь, в котором ключи выступают в качестве целых чисел, вместо строк. Далее, мы извлекли ключи из словаря. Каждый раз, когда вы взываете метод keys(), он возвращает неупорядоченный список ключей. Если вы выведите их, и увидите, что они расположен в порядке по возрастанию, то это просто случайность. Теперь у нас есть доступ к ключам словаря, которые хранятся в переменной, под названием keys. Мы сортируем наш список, после чего используем цикл for в нем. Теперь мы готовы к тому, чтобы сделать все немного интереснее.
Оператор continue
Оператор continue начинает следующий проход цикла, минуя оставшееся тело цикла (for или while)
>>> >>> for i in 'hello world': . if i == 'o': . continue . print(i * 2, end='') . hheellll wwrrlldd
Оператор break
Оператор break досрочно прерывает цикл.
>>> >>> for i in 'hello world': . if i == 'o': . break . print(i * 2, end='') . hheellll
Волшебное слово else
Слово else, примененное в цикле for или while, проверяет, был ли произведен выход из цикла инструкцией break, или же “естественным” образом. Блок инструкций внутри else выполнится только в том случае, если выход из цикла произошел без помощи break.
>>> >>> for i in 'hello world': . if i == 'a': . break . else: . print('Буквы a в строке нет') . Буквы a в строке нет
Искусство написания циклов на Python
Цикл for — самый базовый инструмент потока управления большинства языков программирования. Например, простой цикл for на C выглядит так:
Не существует более изящного способа написания цикла for на C. В сложных случаях обычно приходится писать уродливые вложенные циклы или задавать множество вспомогательных переменных (например, как i в показанном выше коде).
К счастью, в Python всё более удобно. В этом языке есть множество хитростей, позволяющих писать более изящные циклы, которые упрощают нашу жизнь. В Python вполне можно избежать вложенных циклов и вспомогательных переменных, и мы даже можем самостоятельно настраивать цикл for .
Эта статья познакомит вас с самыми полезными трюками по написанию циклов на Python. Надеюсь, она поможет вам ощутить красоту этого языка.
Одновременно получаем значения и индексы
Частым примером использования цикла for является получение индексов и значений из списка. Когда я начинал изучать Python, то писал свой код таким образом:
for i in range(len(my_list)): print(i, my_list[i])
Разумеется, он работал. Но это решение не в стиле Python. Спустя несколько месяцев я узнал стандартный способ реализации в стиле Python:
for i, v in enumerate(my_list): print(i, v)
Как мы видим, встроенная функция enumerate упрощает нам жизнь.
Как избежать вложенных циклов с помощью функции Product
Вложенные циклы — это настоящая головная боль. Они могут снизить читаемость кода и усложнить его понимание. Например, прерывание вложенных циклов обычно реализовать не так просто. Нам нужно знать, где прерван самый внутренний цикл, второй по порядку внутренний цикл, и так далее.
К счастью, в Python существует потрясающая функция product из встроенного модуля itertools . Мы можем использовать её, чтобы не писать множество вложенных циклов.
Давайте убедимся в её полезности на простом примере:
list_a = [1, 2020, 70] list_b = [2, 4, 7, 2000] list_c = [3, 70, 7] for a in list_a: for b in list_b: for c in list_c: if a + b + c == 2077: print(a, b, c) # 70 2000 7
Как мы видим, нам требуется три вложенных цикла, чтобы получить из трёх списков три числа, сумма которых равна 2077. Код не очень красив.
А теперь давайте попробуем использовать функцию product .
from itertools import product list_a = [1, 2020, 70] list_b = [2, 4, 7, 2000] list_c = [3, 70, 7] for a, b, c in product(list_a, list_b, list_c): if a + b + c == 2077: print(a, b, c) # 70 2000 7
Как мы видим, благодаря использованию функции product достаточно всего одного цикла.
Так как функция product генерирует прямое произведение входящих итерируемых данных, она позволяет нам во многих случаях избежать вложенных циклов.
Используем модуль Itertools для написания красивых циклов
На самом деле, функция product — это только вершина айсберга. Если вы изучите встроенный модуль Python itertools , то перед вами откроется целый новый мир. Этот набор инструментов содержит множество полезных методов, покрывающих наши потребности при работе с циклами. Их полный список можно найти в официальной документации. Давайте рассмотрим несколько примеров.
Создаём бесконечный цикл
Существует не меньше трёх способов создания бесконечного цикла:
1. При помощи функции count :
natural_num = itertools.count(1) for n in natural_num: print(n) # 1,2,3.
many_yang = itertools.cycle('Yang') for y in many_yang: print(y) # 'Y','a','n','g','Y','a','n','g'.
many_yang = itertools.repeat('Yang') for y in many_yang: print(y) # 'Yang','Yang'.
Комбинируем несколько итераторов в один
Функция chain() позволяет объединить несколько итераторов в один.
from itertools import chain list_a = [1, 22] list_b = [7, 20] list_c = [3, 70] for i in chain(list_a, list_b, list_c): print(i) # 1,22,7,20,3,70
Выделяем соседние дублирующиеся элементы
Функция groupby используется для выделения соседних дублирующихся элементов в итераторе и их соединения.
from itertools import groupby for key, group in groupby('YAaANNGGG'): print(key, list(group)) # Y ['Y'] # A ['A'] # a ['a'] # A ['A'] # N ['N', 'N'] # G ['G', 'G', 'G']
Как показано выше, соседние одинаковые символы соединены вместе. Более того, мы можем указать функции groupby способ определения идентичности двух элементов:
from itertools import groupby for key, group in groupby('YAaANNGGG', lambda x: x.upper()): print(key, list(group)) # Y ['Y'] # A ['A', 'a', 'A'] # N ['N', 'N'] # G ['G', 'G', 'G']
Самостоятельно настраиваем цикл
Изучив представленные выше примеры, давайте задумаемся о том, почему циклы for в Python настолько гибки и изящны. Насколько я понимаю, это из-за того, что мы можем применять в итераторе цикла for функции. Во всех рассмотренных выше примерах в итераторе всего лишь используются специальные функции. Все трюки имеют одинаковый шаблон:
for x in function(iterator)
Сам встроенный модуль itertools всего лишь реализует за нас самые распространённые функции. Если мы забудем функцию или не сможем найти нужную нам, то можем просто написать её самостоятельно. Если быть более точным, то эти функции являются генераторами. Именно поэтому мы можем генерировать с их помощью бесконечные циклы.
По сути, мы можем настроить цикл for под себя, как сделали бы это с настраиваемым генератором.
Давайте рассмотрим простой пример:
def even_only(num): for i in num: if i % 2 == 0: yield i my_list = [1, 9, 3, 4, 2, 5] for n in even_only(my_list): print(n) # 4 # 2
Как видно из приведённого выше примера, мы определили генератор под названием even_only . Если мы используем этот генератор в цикле for, итерация будет происходить только для чётных чисел из списка.
Разумеется, этот пример приведён только для объяснения. Существуют и другие способы выполнения тех же действий, например, использование представления списков.
my_list = [1, 9, 3, 4, 2, 5] for n in (i for i in my_list if not i % 2): print(n) # 4 # 2
Вывод
Задачу создания циклов на Python можно решать очень гибко и изящно. Чтобы писать удобные и простые циклы, мы можем использовать встроенные инструменты или даже самостоятельно определять генераторы.
На правах рекламы
Надёжный сервер в аренду, создавайте свою конфигурацию в пару кликов и начинайте работать уже через минуту. Всё будет работать без сбоев и с очень высоким uptime!