Циклы в Python
При написании программ часто возникает потребность делать одно и то же действие для нескольких объектов. Например, сохранить 5 пользователей:
user1.save() user2.save() user3.save() user4.save() user5.save()
Кода пока не очень много, но что будет, когда пользователей будет 20? А что если нужно обработать 3 миллиона пользователей вашего сайта? Помогут циклы.
Цикл по списку
Цикл — это запуск одного и того же кода для каждого элемента в списке. Вот как выглядит пример выше с использованием списка и циклов:
users = [user1, user2, user3, user4, user5] for user in users: user.save()
Каждый элемент списка users по очереди подставится в переменную user и для него запустится код с отступом.
Что, всё ещё копипастить пользователей в список? Нет, чаще всего такое не требуется и код выглядит так:
users = get_users_from_database() # возвращает список всех пользователей for user in users: user.do_something() # работа с каждым пользователем по очереди user.save()
Снова, каждый пользователь по очереди попадёт в переменную user , у него вызовется метод .do_something() , а затем метод .save() .
Цикл по словарю
Словарь очень легко можно превратить в 2 списка:
capitals = "Russia": "Moscow", "England": "London", "China": "Beijing", "Italy": "Rome" >
Первый список — ключи словаря (первые элементы в парах):
print(capitals.keys()) # ['Russia', 'England', 'China', 'Italy']
Второй список — значения (вторые элементы в парах):
print(capitals.values()) # ['Moscow', 'London', 'Beijing', 'Rome']
По умолчанию, если передать в for словарь, он начнёт перебирать ключи:
for country in capitals: print(country) # Russia # England # China # Italy
Но так же через ключи словаря можно добраться и до значений:
for country in capitals: capital = capitals[country] print("столица <> это <>".format(country,capital)) # столица Russia это Moscow # столица England это London # столица China это Beijing # столица Italy это Rome
В Python есть ещё один способ добраться до значений словаря, использовать .items() . Этот метод превращает словарь в список кортежей:
print(capitals) # # "Russia": "Moscow", # "England": "London", # "China": "Beijing", # "Italy": "Rome" # > print(capitals.items()) # [ # ('Russia', 'Moscow'), # ('England', 'London'), # ('China', 'Beijing'), # ('Italy', 'Rome') # ]
И теперь цикл сможет итерироваться сразу по двум переменным:
for country, capital in capitals.items(): print("столица <> это <>".format(country, capital)) # столица Russia это Moscow # столица England это London # столица China это Beijing # столица Italy это Rome
Выполнить код несколько раз
Что, если нужно выполнить код заранее известное количество раз? например, сгенерировать 10 случайных чисел и вывести на экран? По какому такому списку мне перебиать элементы?
В таком случаевыручает функция range() .
Что она делает проще показать на примерах:
- range(5) — вернёт список из 5 элементов, начинаяс нуля: [0, 1, 2, 3, 4]
- range(2,10) — вернёт список из элементов от 2 до 10: [2, 3, 4, 5, 6, 7, 8, 9]
- range(2,10,3) — вернёт список из каждого третьего элемента от 2 до 10: [2, 5, 8]
Теперь, научившись генерировать списки нужной длины, можно сгенерировать 10 случайных чисел:
import random for number in range(10): print(random.randint(1,100))
В терминал выведется 10 случайных чисел от 1 до 100. Работает так же, как и ранее: range(10) — это список с числами от 0 до 9. Они по очереди подставятся в переменную number , но ни на что не повлияют, т.к. в коде «внутри for » переменная number не используется.
Строка — тоже “список”
Python запросто переводит одни типы данных в другие. Он может притвориться, что строка — это список из её символов:
text = "Девман" for letter in text: print(letter) # Д # е # в # м # а # н
Можно превратить строку в список более явно с помощью функции list() :
text = "Девман" my_list = list(text) print(my_list) # ['Д', 'е', 'в', 'м', 'а', 'н']
Что дальше
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.
Циклы со списками в Python
В статье про «Операции со списками» мы разобрали, как составить простой список, и научились работать с отдельными его элементами. В этой главе узнаем, как выполнить цикл по всему списку, независимо от его длины, используя всего несколько строк кода. Циклы позволяют выполнять одно и то же действие или набор действий с каждым элементом в списке. В результате вы сможете эффективно работать со списками любой длины, в том числе с тысячами или даже миллионами элементов.
Цикл по всему списку
Часто необходимо просмотреть все записи в списке, выполняя одну и ту же задачу с каждым элементом. Например, в игре вам может потребоваться переместить каждый элемент на экране на одинаковую величину, или в списке чисел вы можете выполнить одну и ту же статистическую операцию для каждого элемента. Или, возможно, нужно отобразить каждый заголовок из списка статей на веб-сайте. Если выполнить одно и то же действие с каждым элементом в списке, можно использовать цикл «for» в Python.
Допустим, у нас есть список имен фокусников, и мы хотим распечатать каждое имя в списке. Мы могли бы сделать это, извлекая каждое имя из списка по отдельности, но такой подход может вызвать несколько проблем. Выводить имена по одному было бы не практично, особенно с длинным списком имен. Кроме того, нам придется менять наш код каждый раз, когда изменяется длина списка. Цикл «for» позволяет избежать этих проблем, позволяя Python самостоятельно решать такую задачу. Давайте использовать цикл for, чтобы распечатать каждое имя в списке магов:
magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician)
Сначала начинаем с определения списка, как мы это делали вводной статье про списки. Затем мы определяем цикл «for». Эта строка говорит Python вытащить имя из списка и сохранить его в переменной «magician». Затем мы говорим Python вывести имя, которое было только что сохранено в переменной «magician». Затем Python повторяет действие по одному разу для каждого имени в списке. Вывод данных представляет собой простой вывод каждого имени в списке:
alice david carolina
Детальный взгляд на циклы
Концепция использования циклов важна, потому что это один из самых распространенных способов, которыми компьютер автоматизирует повторяющиеся задачи. Например, в простом цикле, который мы использовали в прошлом примере, Python сначала читает первую строку цикла:
for magician in magicians:
Эта строка указывает Python извлечь первое значение из списка и сохранить его в переменной magician. Это первое значение — «alice». Затем Python читает следующую строку:
print(magician)
Python выводит текущее значение, которое является значение «alice». Так как список содержит больше значений, Python возвращается к первой строке цикла:
for magician in magicians:
Python получает следующее значение в списке, «david», и сохраняет это значение в переменной и выполняет строку:
print(magician)
Python снова выводит текущее значение в переменной magician, которое является «david». Python повторяет весь цикл еще раз с последним значением в списке, «carolina». Так как в списке больше нет значений, Python переходит на следующую строку в программе. В этом случае после цикла «for» ничего не приходит, поэтому программа просто завершается.
Когда вы впервые используете циклы, имейте в виду, что набор шагов повторяется один раз для каждого элемента в списке, независимо от того, сколько элементов в списке. Если в вашем списке есть миллион элементов, Python повторяет эти шаги миллион раз — и обычно очень быстро.
Также помните, что при написании собственных циклов «for» вы можете выбрать любое имя для временной переменной, которая содержит каждое значение в списке. Следует знать, что следует выбрать значимое имя, представляющее один элемент из списка. Например, вот хороший способ запустить цикл «for» для списка кошек, списка собак и общего списка элементов:
for cat in cats: for dog in dogs: for item in list_of_items:
Подобное назначение имён могут помочь вам следить за действиями, выполняемыми над каждым элементом в цикле for. Использование имен единственного и множественного числа может помочь вам определить, работает ли раздел кода с одним элементом из списка или со всем списком.
Возможности использования циклов
Вы можете делать что угодно с каждым элементом в цикле for. Давайте переделаем немного предыдущий пример, сделав вывод сообщения каждому из списка, сообщив им, что они выполнили замечательный трюк:
magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!")
Единственное отличие в этом коде состоит в том, что мы составляем сообщение каждому из списка, начиная с его имени. В первый раз в цикле значение magician = «Aice», поэтому Python запускает первое сообщение с именем ‘Alice’. Затем выводится сообщение начнется с «david», потом сообщение начнется с «Carolina». Выводим сообщение для каждого имени в списке:
Alice, that was a great trick! David, that was a great trick! Carolina, that was a great trick!
Можно написать столько строк кода, сколько захотите в цикле for. Каждая строка с отступом, следующая за строкой «for magician in magicians», рассматривается внутри цикла, и каждая строка с отступом выполняется один раз для каждого значение в списке. Поэтому вы можете выполнять вывод столько, сколько в этом есть необходимости с каждым значением в списке. Давайте добавим вторую строку к нашему сообщению, сообщая каждому имени из списка, что мы с нетерпением ждем его следующего трюка:
magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") print("I can't wait to see your next trick, " + magician.title() + ".\n")
Так как мы выделили два операторы вывода данных, каждая строка будет выполнена один раз для каждого имени в списке. Новая строка («\n») во втором операторе вывода данных содержит пустую строку после каждого прохождения цикла. Это создает набор сообщений, которые аккуратно сгруппированы для каждого человека в списке:
Alice, that was a great trick! I can't wait to see your next trick, Alice. David, that was a great trick! I can't wait to see your next trick, David. Carolina, that was a great trick! I can't wait to see your next trick, Carolina.
Можно использовать столько строк, сколько хотите в своих циклах for. На практике бывает полезно выполнять ряд различных операций с каждым элементом в списке, когда вы используете цикл for.
Действия после использования циклов
Что происходит после завершения цикла for? Обычно можно обобщить блок вывода или перейти к другим действиям, которые должна выполнять программа.
Любые строки кода после цикла for, которые не имеют отступов, выполняются один раз без повторения. Давайте напишем благодарность всем в нашем списке, например, поблагодарив их за прекрасное шоу. Чтобы отобразить это групповое сообщение после того, как все отдельные сообщения были выведены, мы помещаем благодарственное сообщение после цикла for без отступа:
magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") print("I can't wait to see your next trick, " + magician.title() + ".\n") print("Thank you, everyone. That was a great magic show!")
Первые два оператора печати повторяются один раз для каждого имени в списке, как вы видели ранее. Однако, поскольку строка дальше не имеет отступа, она печатается только один раз:
Alice, that was a great trick! I can't wait to see your next trick, Alice. David, that was a great trick! I can't wait to see your next trick, David. Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Thank you, everyone. That was a great magic show!
Когда обрабатываются данные с помощью цикла for, вы обнаружите, что это хороший способ подвести итог операции, которая была выполнена для всего набора данных. Например, вы можете использовать цикл for для инициализации игры, просматривая список персонажей и отображая каждого персонажа на экране. После этого вы можете написать блок с отступом, который отображает кнопку «Воспроизвести сейчас» после того, как все данные выведены на экран.
Циклы со срезом данных в списке
В статье про дополнительные операции со списками мы узнали, как можно работать со срезами данных. Также следует отметить, что можно производить цикл «for» в срезе списка в случаях, когда необходимо выбрать какие-либо элементы в нём и произвести последующие операции с данными. В следующем примере мы перебираем циклом первых трех игроков и выводим их имена как часть простого списка:
players = ['charles', 'martina', 'michael', 'florence', 'eli'] print("Here are the first three players on my team:") for player in players[:3]: print(player.title())
Вместо того, чтобы просматривать весь список игроков, Python просматривает только первые три имени и выводит их:
Here are the first three players on my team: Charles Martina Michael
Работа с определёнными данными в списках очень необходимо в ряде ситуаций. Например, когда вы создаете игру, можно сохранять окончательный счет игрока в список каждый раз, когда он завершает игру. Затем можно получить три лучших результата игрока, отсортировав список по убыванию и выбрав срез, включающий только первые три результата. Когда вы работаете с данными, вы можете использовать срезы для обработки данных в блоках определенного размера. Или, когда вы создаете веб-приложение, вы можете использовать срезы для отображения информации в серии страниц с соответствующим количеством информации на каждой странице.
Примечание
Основная статья: Циклы со словарями в Python
В этой статье мы детально познакомились с использованием циклов в списках, которые применяются во время программирования игр, приложений и других программ. Далее можно изучить, как применяются циклы со словарями в Python, что также полезно. Если же есть вопросы, комментарии, иные сообщения, то оставляйте их на странице обсуждения.
Другие статьи о Python
Язык программирования Python
- Операции со строкой
- Операции со списками
- Дополнительные операции со списками
- Операции со словарями
- Циклы
- Циклы со списками
- Дополнительные операции со словарями
- Ввод данных
- Условные операторы
- Циклы со словарями
- Функции
- Классы
- Работа с файлами в Python
- Тестирование кода в Python
Цикл for — Python: Списки
Ранее мы рассматривали цикл while . Эта конструкция предназначена для повторения некоего набора действий — все, что выходит за рамки повторения, требует дополнительных средств для хранения состояния.
Возьмем для примера счетчик, который мы изменяем в цикле. При работе с коллекциями нам нужно как-то выбирать, с каким элементом мы работаем в текущей итерации. Так что же, использовать переменную-счетчик каждый раз?
Любой программист всегда стремится автоматизировать рутинную работу, и авторы языков — не исключение. Поэтому в Python для работы с коллекциями существует другой вид цикла — цикл for .
Стоит сразу отметить, что этот цикл не похож на циклы с тем же названием в других языках программирования. Во многих языках этот цикл всего лишь дополняет условие завершения цикла переменной-счетчиком.
Python пошел дальше, поэтому в этом языке цикл for сразу перебирает элементы входной коллекции, и думать об индексе чаще всего вообще не нужно.
Синтаксис
Цикл for устроен очень просто:
for element in collection: print(element) # this is body of cycle
Заметьте, в простейшем случае у цикла даже нет явного условия завершения. Цикл просто останавливается, когда в коллекции заканчиваются элементы.
Пример выше сработает для кортежей и списков — в этом случае будут выведены все элементы. А еще коллекции можно проитерировать — так называют обход коллекции. В таком случае переменная цикла ( element ) будет поочередно содержать все символы строки:
for c in 'Hello!': print(c) # => H # => e # => l # => l # => o # => !
Но что же делать, если нам нужно не просто получить элементы списка один за другим, но и изменить эти элементы? Ведь для этого нам понадобится индекс каждого элемента.
На этот случай в Python есть удобная функция «пронумеровать» — enumerate . Эта функция снабжает каждый элемент индексом, складывая каждый индекс вместе с элементом в кортеж. Кортежи эти, как правило, прямо в первой строке цикла и распаковывают:
items = ['foo', 'bar', 'baz'] for (index, elem) in enumerate(items): print(f'index> elem>') # => 0 foo # => 1 bar # => 2 baz
В этом цикле мы вывели каждый элемент рядом с его индексом.
Теперь посмотрим на такой пример:
items = ['foo', 'bar', 'baz'] for (index, _) in enumerate(items): items[index] += '!' print(items) # => ['foo!', 'bar!', 'baz!']
Здесь мы изменяем каждый элемент по его индексу в оригинальном списке. Но мы вообще не используем сами элементы — только их индексы. Поэтому вместо переменной цикла, в которую распаковываются элементы, у нас стоит прочерк.
Это не какая-то особая переменная, а всего лишь соглашение: в Python часто незначимые в этом контексте вещи записывают в переменную _ .
Заметьте: в последнем примере речь и шла об индексах, но мы все равно не использовали длину коллекции. Функция enumerate тоже знает, где остановиться — в конце исходной коллекции.
Управление циклом с помощью break и continue
Иногда не нужно доходить до конца коллекции. Например, при поиске элемента, удовлетворяющего некоему условию. Как только мы нашли первый подходящий элемент, нам неплохо бы сэкономить ресурсы и завершить цикл.
Такой ранний выход из цикла делается с помощью команды break . Вот цикл поиска первого положительного числа:
items = [-2, 0, -10, 3, 5, -1] for item in items: if item > 0: break print(item) # => 3
Как вы могли заметить, переменная цикла оказалась доступна и после его завершения. Однако если коллекция окажется пустой, то переменная не будет определена — имейте это ввиду.
Этот код, кажется, работает как надо. Однако если в списке не встретится ни одного положительного числа, то в переменной item окажется просто последний элемент списка.
Как же понять, что мы ничего не нашли? На помощь приходит else . В цикле else выполняется, если цикл так и не прервался с помощью break . Для алгоритмов поиска — это идеальный вариант. Перепишем наш пример с применением else :
items = [-2, 0, -10, -1] for item in items: if item > 0: break else: item = None print(item) # => None
Теперь представим ситуацию, что мы в процессе выполнения тела цикла поняли, что остаток тела выполнять незачем и можно сразу перейти к следующей итерации.
Для перехода к следующей итерации предназначена команда continue . Ее использование продемонстрирует следующий пример: мы читаем строки, содержащие строчки кода, но нам не нужно обрабатывать код тех строчек, которые начинаются с символа # . Вот так будет выглядеть код:
lines_of_code = [ '# begin of example', 'echo 123', 'cd foo', '# end'] for line in lines_of_code: if line[:1] == '#': continue # Здесь происходит обработка кода print(line) # => echo 123 # => cd foo
Конечно, мы могли бы обойтись условной конструкцией. Однако в этом случае код, обрабатывающий нужные строки, был бы вложен глубже. А нам нужно стремиться держать вложенность кода в разумных пределах, иначе код очень быстро станет очень сложным для прочтения.
break , continue , else и цикл while
Ветка else и команды break и continue доступны и для цикла while . Вот комплексный пример, демонстрирующий все эти возможности:
tries_count = 3 while tries_count: print('>>> ', end='') command = input() if not command: continue if command in ('echo', 'cd', 'help'): break print('Unknown command!') tries_count -= 1 else: print('Too many bad tries!') command = None
Этот код просит пользователя ввести одну из команд, игнорирует пустой ввод, ограничивает количество попыток ввода. Подумайте, какая часть тела цикла за что отвечает.
Цикл for и изменяемые коллекции
Хотим предостеречь от изменения состава списка во время обхода его же в цикле for . Программа может завершиться с ошибкой, если вы будете менять список, по которому проходитесь — например, удалять или добавлять новые элементы. Лучше наполнять новый список в процессе обхода старого.
Если вы хотите обязательно изменить состав исходного списка, то обходите в цикле его копию:
for x in original_list[:]: original_list.pop(0)
Еще можно создать временный список, а потом очистить исходный и добавить элементы из временного:
new_list = [] for x in original_list: . original_list[:] = [] # удаляем старое содержимое original_list.extend(new_list)
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Итерация по списку в Python по частям
Иногда при работе с Python возникает необходимость обрабатывать данные из списка не по одному элементу, а группами. Например, может потребоваться работать с четырьмя элементами списка одновременно.
Возьмём для примера список целых чисел:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Требуется обработать этот список по четыре элемента за раз. Одним из наиболее простых и интуитивно понятных подходов к этой задаче является использование цикла for и функции range():
for i in range(0, len(numbers), 4): chunk = numbers[i:i+4] print(chunk)
В этом примере каждую итерацию цикла мы берем срез из четырех элементов списка. Третий аргумент функции range() определяет шаг, с которым будет двигаться цикл — в данном случае, 4.
Однако, в Python есть еще более «питоновский» способ решения этой задачи — использование генераторов. Генераторы — это особый тип функций, которые позволяют нам создавать последовательности данных «на лету», без необходимости хранения всей последовательности в памяти.
Вот как можно реализовать нашу задачу с помощью генератора:
def chunks(lst, n): for i in range(0, len(lst), n): yield lst[i:i+n] for chunk in chunks(numbers, 4): print(chunk)
В этом примере мы создаем функцию-генератор chunks(), которая принимает на вход список и размер чанка. Внутри функции мы используем тот же подход с циклом for и функцией range(), но вместо того чтобы сразу обрабатывать данные, мы используем ключевое слово yield, чтобы «выдать» очередной чанк.
Затем мы можем использовать наш генератор в цикле for, как будто это обычный список. Главное преимущество такого подхода в том, что данные обрабатываются «по мере необходимости», что позволяет значительно сэкономить память при работе с большими списками.
