- Цикл for в Python: тонкости написания
- Выводим индекс и значение одновременно
- Избавляемся от вложенных циклов с помощью функции product
- Используем модуль Itertools для написания невероятных циклов
- Создаем бесконечный цикл
- Объединяем несколько итераторов в один
- Выводим повторяющиеся элементы и количество их повторений
- Самостоятельно настраиваем цикл for
- Вывод
- Искусство написания циклов на Python
- Одновременно получаем значения и индексы
- Как избежать вложенных циклов с помощью функции Product
- Используем модуль Itertools для написания красивых циклов
- Создаём бесконечный цикл
- Комбинируем несколько итераторов в один
- Выделяем соседние дублирующиеся элементы
- Самостоятельно настраиваем цикл
- Вывод
- На правах рекламы
Цикл for в Python: тонкости написания
Цикл for — одна из базовых управляющих конструкций в любом языке программирования. Простейший цикл в языке Си выглядит так:
В Си нет более элегантного способа написать цикл for. В более сложных сценариях мы обычно прибегаем к вложенным циклам и множеству вспомогательных переменных (например, i в примере выше).
К счастью, в Python все намного удобнее. У этого языка есть возможности, позволяющие писать лаконичные циклы — это очень упрощает нашу жизнь. В Python можно избежать вложенных циклов, а вспомогательные переменные объявлять вовсе не обязательно. А еще мы сами можем настроить цикл for !
В этой статье мы расскажем вам о тонкостях написания цикла for . Надеемся, вы прочувствуете всю красоту Python.
Выводим индекс и значение одновременно
Обыденный сценарий: мы работаем со списком и нам нужно вывести и индексы, и соответствующие значения. Когда я только начал изучать Python, мой код выглядел примерно так:
for i in range(len(my_list)): print(i, my_list[i])
Да, это работает. Но это недостаточно «питонично». Через несколько месяцев изучения Python я решал эту задачу так:
for i, v in enumerate(my_list): print(i, v)
Как видите, встроенная функция enumerate значительно упрощает нашу жизнь.
Избавляемся от вложенных циклов с помощью функции product
Вложенные циклы — настоящая головная боль. Они усложняют не только сам код, но и его читаемость. Выход из этих циклов — задача тоже сложная. Чтобы найти ошибку, приходится приложить много усилий, ведь нужно проверить каждый внутренний цикл.
К счастью, существует очень полезная встроенная функция — product . Она является частью встроенного модуля Python — 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 — лишь вершина айсберга. Изучение модуля itertools сравнимо с открытием нового мира. В нем содержится множество полезных методов, которые могут упростить любой цикл. Полный список вы можете найти в официальной документации.
Рассмотрим несколько примеров.
Создаем бесконечный цикл
В модуле itertools есть как минимум три метода для создания бесконечных циклов:
natural_num = itertools.count(1) for n in natural_num: print(n) # 1,2,3.
import itertools many_yang = itertools.cycle('Hello') for y in many_yang: print(y) # 'H','e','l','l','o','H','e','l'.
many_yang = itertools.repeat('Hello') for y in many_yang: print(y) # 'Hello','Hello'.
Объединяем несколько итераторов в один
Функция 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('Pyttthhhonissst'): print(key, list(group)) # P ['P'] # y ['y'] # t ['t', 't', 't'] # h ['h', 'h', 'h'] # o ['o'] # n ['n'] # i ['i'] # s ['s', 's', 's'] # t ['t']
Как видите, дублирующиеся буквы сгруппированы. Более того, мы можем расширить функционал groupby() . Например, указать, что нужно игнорировать регистр:
from itertools import groupby for key, group in groupby('PyYyYTTthHOoOnisst', lambda x: x.upper()): print(key, list(group)) # P ['P'] # Y ['y', 'Y', 'y', 'Y'] # T ['T', 'T', 't'] # H ['h', 'H'] # O ['O', 'o', 'O'] # N ['n'] # I ['i'] # S ['s', 's'] # T ['t']
Самостоятельно настраиваем цикл for
После ознакомления с примерами пора наконец разобраться, почему же циклы в Python такие гибкие и изящные. Этими своими свойствами они обязаны тому, что к итератору в цикле for можно применять функции. Во всех примерах, приведенных выше, к итераторам применялась какая-нибудь функция. Шаблон в целом выглядит так:
for x in function(iterator)
То есть, суть itertools проста — этот модуль применяет часто используемые функции к итератору. Если вы забыли какую-либо функцию из 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 . Если мы встроим этот генератор в цикл, то итерация будет происходить только по четным элементам списка.
Пример выше — лишь для объяснения принципа работы. Существует множество других способов решения этой задачи — например, генераторы списков.
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 могут быть изящны и гибки. Такими их делают встроенные функции и генераторы.
Искусство написания циклов на 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!