upd:
262.5K
19

Цикл "for" в Python — универсальная управляющая конструкция

Содержание:развернуть

Циклы являются мощнейшим инструментом, предоставляемым высокоуровневыми языками программирования. Эти управляющие конструкции позволяют многократно выполнять требуемую последовательность инструкций. Циклы в языке Python представлены двумя основными конструкциями: while и for.

Подробнее о циклах while вы можете прочитать здесь:

Применение циклов

Концепция циклов — это не просто очередная абстрактная выдумка программистов. Повторяющиеся раз за разом операции окружают нас и в реальной жизни:

🥣 добавление щепотки приправ в варящийся бульон и помешивание его до тех пор, пока пакетик специй не закончится.
🕙 следование строгому расписанию каждый будний день, пока не наступят долгожданные выходные.
🌄 даже банальная смена времён года.

— всё это циклы, и представить нормальную жизнь без них попросту невозможно.

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

print(1) print(2) print(3) # ... # 9999999995 строк # ... print(9999999998) print(9999999999)

Циклы же позволяют уместить такую многокилометровую запись в изящную и простую для понимания конструкцию, состоящую всего из двух строчек:

for i in range(1, 10000000000): print(i)

Смысл её крайне прост. В основе цикла for лежат последовательности, и в примере выше это последовательность чисел от 1 до 9999999999. for поэлементно её перебирает и выполняет код, который записан в теле цикла. В частности, для решения данной задачи туда была помещена инструкция, позволяющая выводить значение элемента последовательности на экран.

Итерации

  • Итерация (Iteration) — это одно из повторений цикла (один шаг или один "виток" циклического процесса). К примеру цикл из 3-х повторений можно представить как 3 итерации.
  • Итерируемый объект (Iterable) — объект, который можно повторять. Проще говоря это объект, который умеет отдавать по одному результату за каждую итерацию.
  • Итератор (iterator) — итерируемый объект, в рамках которого реализован метод __next__, позволяющий получать следующий элемент.

👉 Чтобы выполнить итерацию, Python делает следующее:

  • Вызывает у итерируемого объекта метод iter(), тем самым получая итератор.
  • Вызывает метод next(), чтобы получить каждый элемент от итератора.
  • Когда метод next возвращает исключение StopIteration, цикл останавливается.
Схема работы цикла "for" в Python

Пример создания итерируемого объекта Для того чтобы создать собственный класс итерируемого объекта, нужно всего лишь внутри него реализовать два метода: __iter__() и __next__():

  • внутри метода __next__ () описывается процедура возврата следующего доступного элемента;
  • метод __iter__() возвращает сам объект, что даёт возможность использовать его, например, в циклах с поэлементным перебором.

Создадим простой строковый итератор, который на каждой итерации, при получении следующего элемента (т.е. символа), приводит его к верхнему регистру:

class ToUpperCase: def __init__(self, string_obj, position=0): """сохраняем строку, полученную из конструктора, в поле string_obj и задаём начальный индекс""" self.string_obj = string_obj self.position = position def __iter__(self): """ возвращаем сам объект """ return self def __next__(self): """ метод возвращает следующий элемент, но уже приведенный к верхнему регистру """ if self.position >= len(self.string_obj): # исключение StopIteration() сообщает циклу for о завершении raise StopIteration() position = self.position # инкрементируем индекс self.position += 1 # возвращаем символ в uppercase-e return self.string_obj[position].upper() low_python = "python" high_python = ToUpperCase(low_python) for ch in high_python: print(ch, end="") > PYTHON

Синтаксис for

Как было замечено, цикл for python — есть средство для перебора последовательностей. С его помощью можно совершать обход строк, списков, кортежей и описанных выше итерируемых объектов.

В простейшем случае он выглядит так:

for item in collection: # do something

Если последовательность collection состоит, скажем, из 10 элементов, for будет поочерёдно обходить их, храня значение текущего элемента в переменной item.

Принцип работы for максимально схож с таковым у циклов foreach, применяемых во многих других высокоуровневых языках.

aliceQuote = "The best way to explain it is to do it." # с помощью цикла for посчитаем количество символов (с пробелами) в строке # зададим счетчик count = 0 # будем посимвольно обходить весь текст for letter in aliceQuote: # на каждой новой итерации: # в переменной letter будет храниться следующий символ предложения; # увеличиваем счетчик на 1; count += 1 print(count) > 39

range() и enumerate()

Вы уже наверняка запомнили, что for работает с последовательностями. В программировании очень часто приходится повторять какую-то операцию фиксированное количество раз. А где упоминается "количество чего-то", существует и последовательность, числовая.

👉 Для того чтобы выполнить какую-либо инструкцию строго определенное число раз, воспользуемся функцией range():

# скажем Миру привет целых пять раз! for i in range(5): print("Hello World!") > Hello World! Hello World! Hello World! Hello World! Hello World!

range() можно представлять, как функцию, что возвращает последовательность чисел, регулируемую количеством переданных в неё аргументов. Их может быть 1, 2 или 3:

  • range(stop);
  • range(start, stop);
  • range(start, stop, step).

Здесь start — это первый элемент последовательности (включительно), stop — последний (не включительно), а step — разность между следующим и предыдущим членами последовательности.

# 0 - начальный элемент по умолчанию for a in range(3): print(a) > 0 1 2 # два аргумента for b in range(7, 10): print(b) > 7 8 9 # три аргумента for c in range(0, 13, 3): print(c) > 0 3 6 9 12
Подробнее о функции range тут:

👉 Чрезвычайно полезная функция enumerate() определена на множестве итерируемых объектов и служит для создания кортежей на основании каждого из элементов объекта. Кортежи строятся по принципу (индекс элемента, элемент), что бывает крайне удобно, когда помимо самих элементов требуется ещё и их индекс.

# заменим каждый пятый символ предложения, начиная с 0-го, на * text = "Это не те дроиды, которых вы ищете" new_text = "" for char in enumerate(text): if char[0] % 5 == 0: new_text += '*' else: new_text += char[1] print(new_text) > *то н* те *роид*, ко*орых*вы и*ете

break и continue

Два похожих оператора, которые можно встретить и в других языках программирования.

  • break — прерывает цикл и выходит из него;
  • continue — прерывает текущую итерацию и переходит к следующей.
# break for num in range(40, 51): if num == 45: break print(num) > 40 41 42 43 44

Здесь видно, как цикл, дойдя до числа 45 и вернув истину в условном выражении, прерывается и заканчивает свою работу.

# continue for num in range(40, 51): if num == 45: continue print(num) > 40 41 42 43 44 46 47 48 49 50

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

else

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

group_of_students = [21, 18, 19, 21, 18] for age in group_of_students: if age < 18: break else: print('Всё в порядке, они совершеннолетние') > Всё в порядке, они совершеннолетние

Best practice

Цикл по списку

Перебрать list в цикле не составляет никакого труда, поскольку список — объект итерируемый:

# есть список entities_of_warp = ["Tzeench", "Slaanesh", "Khorne", "Nurgle"] # просто берём список, «загружаем» его в цикл и без всякой задней мысли делаем обход for entity in entities_of_warp: print(entity) > Tzeench Slaanesh Khorne Nurgle

Так как элементами списков могут быть другие итерируемые объекты, то стоит упомянуть и о вложенных циклах. Цикл внутри цикла вполне обыденное явление, и хоть количество уровней вложенности не имеет пределов, злоупотреблять этим не следует. Циклы свыше второго уровня вложенности крайне тяжело воспринимаются и читаются.

strange_phonebook = [ ["Alex", "Andrew", "Aya", "Azazel"], ["Barry", "Bill", "Brave", "Byanka"], ["Casey", "Chad", "Claire", "Cuddy"], ["Dana", "Ditrich", "Dmitry", "Donovan"] ] # это список списков, где каждый подсписок состоит из строк # следовательно можно (зачем-то) применить тройной for # для посимвольного чтения всех имён # и вывода их в одну строку for letter in strange_phonebook: for name in letter: for character in name: print(character, end='') > A l e x A n d r e w A y a A z a z e l B a r ...

Цикл по словарю

Чуть более сложный пример связан с итерированием словарей. Обычно, при переборе словаря, нужно получать и ключ и значение. Для этого существует метод .items(), который создает представление в виде кортежа для каждого словарного элемента.

Цикл, в таком случае, будет выглядеть следующим образом:

# создадим словарь top_10_largest_lakes = { "Caspian Sea": "Saline", "Superior": "Freshwater", "Victoria": "Freshwater", "Huron": "Freshwater", } # обойдём его в цикле for и посчитаем количество озер с солёной водой и количество озёр с пресной salt = 0 fresh = 0 # пара "lake, water", в данном случае, есть распакованный кортеж, где lake - ключ словаря, а water - значение. # цикл, соответственно, обходит не сам словарь, а его представление в виде пар кортежей for lake, water in top_10_largest_lakes.items(): if water == 'Freshwater': fresh += 1 else: salt += 1 print("Amount of saline lakes in top10: ", salt) print("Amount of freshwater lakes in top10: ", fresh) > Amount of saline lakes in top10: 1 > Amount of freshwater lakes in top10: 3

Цикл по строке

Строки, по сути своей — весьма простые последовательности, состоящие из символов. Поэтому обходить их в цикле тоже совсем несложно.

word = 'Alabama' for w in word: print(w, end=" ") > A l a b a m a

Цикл for с шагом

Цикл for с шагом создается при помощи уже известной нам функции range, куда, в качестве третьего по счету аргумента, нужно передать размер шага:

# выведем числа от 100 до 1000 с шагом 150 for nums in range(100, 1000, 150): print(nums) > 100 250 400 550 700 850

Цикл for со счетчиком итераций

Счетчик итераций может понадобиться, если обходить циклом for списки с данными. Например, если нужно логировать номер каждой итерации или остановить цикл for по достижении лимита.

В цикле for нет встроенного счетчика итераций, но его можно сделать несколькими способами:

Способ #1 — через функцию enumerate(), она генерирует кортеж вида (индекс элемента, элемент):

step_names = ["up", "down", "up", "up", "down"] for i, step_name in enumerate(step_names): print(f"step #{i + 1} — {step_name}") > step #1 — up > step #2 — down > step #3 — up > step #4 — up > step #5 — down

Способ #2 — через функцию zip(), она группирует данные в кортежи и останавливается, когда заканчиваются элементы:

step_names = ["up", "down", "up", "up", "down"] step_names_len = len(step_names) for i, step_name in zip(range(step_names_len), step_names): # лимит = 5 print(f"step #{i + 1} — {step_name}") > step #1 — up > step #2 — down > step #3 — up > step #4 — up > step #5 — down

Обратный цикл for

Если вы еще не убедились в том, что range() полезна, то вот ещё пример: благодаря этой функции можно взять и обойти последовательность в обратном направлении.

# выведем числа от 40 до 50 по убыванию # для этого установим step -1 for nums in range(50, 39, -1): print(nums) > 50 49 48 47 46 45 44 43 42 41 40

for в одну строку

Крутая питоновская фишка, основанная на так называемых list comprehensions или, по-русски, генераторов. Их запись, быть может, несколько сложнее для понимания, зато очевидно короче и, по некоторым данным, она работает заметно быстрее на больших массивах данных.

В общем виде генератор выглядит так:

[результирующее выражение | цикл | опциональное условие]

Приведем пример, в котором продублируем каждый символ строки inputString:

# здесь letter * 2 — результирующее выражение; for letter in inputString — цикл, а необязательное условие опущено double_letter = [letter * 2 for letter in "Banana"] print(double_letter) > ['BB', 'aa', 'nn', 'aa', 'nn', 'aa']

Другой пример, но теперь уже с условием:

# создадим список, что будет состоять из четных чисел от нуля до тридцати # здесь if x % 2 == 0 — необязательное условие even_nums = [x for x in range(30) if x % 2 == 0] print(even_nums) [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]
53
😭
32
😕
35
😃
288
😍
Комментарии (19)
Сначала популярные
Сначала новые
По очереди
Phoenix
7 мес. 2 дня назад

Автор данной статьи настоящий гигачад, спасибо)

10
ответить
Студент
4 мес. назад

Здравствуйте, как сделать чтобы цикл for автоматически присваивал номерацию? Пример: 1 up 2 up 3 up

8
ответить
Pythonchik
19 дней назад

Добрый день! Добавил информацию в раздел "Best practice → Цикл for со счетчиком итераций".

1
ответить
Nikita
4 мес. 1 день назад

for i in data и чтобы здесь можно было ввести ограничение сколько раз. Так можно?

7
ответить
Pythonchik
4 мес. 1 день назад

В цикле for нет возможности задать лимит повторений. Но вашу задачу можно решить как минимум 3-мя способами.

Способ #1 — функция enumerate() генерирует кортежи вида (индекс элемента, элемент):

for i, element in enumerate(data): if i >= 3: # лимит = 3 break # ниже основной код

Способ #2 — функция zip() группирует данные в кортежи и останавливается, когда заканчиваются элементы:

for _, item in zip(range(3), data): # лимит = 3 print(item)

Способ #3 — использовать срезы (для списков, кортежей, строк):

for item in data[:3]: # лимит = 3 print(item)
3
ответить
аня
20 дней назад

А как сделать цикл for с шагом 0.1??

4
ответить
Pythonchik
19 дней назад

Если вы генерируете список чисел через range, то указать шаг 0.1 не получится. Информация есть в статье про range, в разделе "range и тип float".

Если вы хотите использовать числа с шагом 0.1 для дальнейших операций с числами, можно сделать так:

for i in range(0, 11, 1): print(i / 10.0) > 0.0 > 0.1 > 0.2 > 0.3 > 0.4 > 0.5 > ..

Альтернаятивный вариант — заранее сгенерировать список чисел с шагом 0.1:

float_numbers = (x / 10.0 for x in range(0, 11, 1)) for i in float_numbers: print(i) > 0.0 > 0.1 > 0.2 > 0.3 > 0.4 > 0.5 > ..
читать дальше
1
ответить
Максим
6 мес. 8 дней назад

Даже для такого новичка как я и то понятно огромное спасибо!

4
ответить
Зачем я начал учить питон...
5 мес. 2 дня назад

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

N = int(input("Введите натуральное число: ")) for N in range(N): # Цикл в последовательности 1-99 if(N % 2 != 0 and N % 3 != 0 and N % 5 != 0): print(N)

Вот такого вида код, то есть в терминале выдастся последовательность, к примеру: 12 13 14 Нужно чтобы в конце было "Всего чисел 3"

1
ответить
Pythonchik
5 мес. 1 день назад

Добрый день! Можно сделать через счётчик:

N = int(input("Введите натуральное число: ")) sum = 0 for N in range(N): # Цикл в последовательности 1-99 if (N % 2 != 0 and N % 3 != 0 and N % 5 != 0): sum += 1 print(N) print(f"Всего чисел {sum}")
2
ответить
еще 1 ответ
Maks
8 мес. 3 дня назад

Не всё было понятно сразу, а так круто.

1
ответить
Pythonchik
8 мес. 3 дня назад

Если что-то непонятно, можете спрашивать в комментариях 😉

1
ответить
Зачем я начал учить питон...
4 мес. 3 дня назад

Доброй ночи Pythonchik! Подскажи пожалуйста как мне в этом коде дописать, чтобы он выводил в терминал 2-9+4=-3 и тому подобное? Буду очень признателен за помощь

q = 0 # переменная, увеличивающася на 1 каждую итерацию, нужна чтобы чередовать + и - n = input() # число, с цифрами которого работаем s = 0 # переменная в коорую посчитаем результат for i in n: # перебиаем цифры числа n q = q + 1 # увеличиваем q на 1 if q % 2 == 1: # если q нечётное s += int(i) # тогда будем прибавлять else: # если q чётное s -= int(i) # тогда будем вычитать print("Знакочередующаяся сумма цифр числа", n, "составляет:", s) # выводим итог на экран print("Программа завершила выполнение")
0
ответить
Pythonchik
4 мес. 3 дня назад

Если вам нужно отображать все операции над цифрами, можно сделать так:

q = 0 # переменная, увеличивающася на 1 каждую итерацию, нужна чтобы чередовать + и - n = input() # число, с цифрами которого работаем s = 0 # переменная в коорую посчитаем результат ops = [] # переменная в коорую пишутся все операции сложения/вычитания for i in n: # перебиаем цифры числа n q = q + 1 # увеличиваем q на 1 if q % 2 == 1: # если q нечётное s += int(i) # тогда будем прибавлять ops.append(f"+{i}") else: # если q чётное s -= int(i) # тогда будем вычитать ops.append(f"-{i}") print(f"Знакочередующаяся сумма цифр числа {n} составляет {''.join(ops)}={s}") # выводим итог на экран print("Программа завершила выполнение")

Из личных рекомендаций по коду, советую ознакомиться с этими статьями:

1
ответить
еще 1 ответ
Шакир
5 мес. 18 дней назад
months = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'] for entity in months: print(months)

Выдаёт текст в скобках на протяжении 12 строк, что делать?

0
ответить
Pythonchik
5 мес. 18 дней назад

Вместо print(months) нужно print(entity).

6
ответить
Uriy76
3 мес. 6 дней назад

Коротко и ясно.

0
ответить
Содержание:развернуть
вверх
Может понравиться
Основы
upd:
Как работает цикл "while" в Python