Управляющие конструкции - if, for, while
Перед чтением: Операторы — общие понятия оператора, операнда, приоритетов и типов операций без привязки к языку.
Сначала: Циклы в коде — общая идея повторений, виды циклов и типичные ошибки без привязки к синтаксису языка.
Python — if, for, while
Ветвление — if / elif / else с отступами вместо {}. Цикл for в Python почти всегда означает «для каждого элемента в …» (for x in items), а не счётчик с тремя частями в заголовке; счётчик — через range(). Списковое включение — компактная форма того же цикла, когда результат сразу собирается в список. while — когда число итераций заранее неизвестно.
Общая схема циклов и типичные ошибки — в циклах в коде (блок "Сначала" выше). Оценка сложности вложенных циклов (O(n²)) с разбором кода — Lab / Big-O — 1128. В задачах на Python те же конструкции встречаются в переборах, FizzBuzz и двойных циклах — Lab / 1122.
Операторы
Play ITЗагрузка интерактивного демо…
Условные операторы
Условные операторы предназначены для ветвления выполнения программы на основе логических выражений.
В Python используется ключевое слово if для начала проверки условия, elif (сокращение от else if) — для дополнительных условий, и else — для блока, выполняемого в случае, если ни одно из предыдущих условий не было истинным.
Синтаксис условной конструкции:
if условие1:
# блок кода 1
elif условие2:
# блок кода 2
else:
# блок кода 3
Каждый блок кода должен быть выделен отступом (PEP 8 рекомендует использовать 4 пробела). Интерпретатор оценивает условия по порядку; выполнение передаётся первому блоку, чьё условие вернуло True. Остальные ветви игнорируются.
Пример:
x = 10
if x > 15:
print("x больше 15")
elif x > 5:
print("x больше 5, но не больше 15")
else:
print("x меньше или равно 5")
Разбор примера:
x = 10создаёт переменную и сохраняет в ней целое число.if x > 15проверяется первым. Условие ложно, блок пропускается.elif x > 5проверяется вторым. Условие истинно, выполняетсяprint(...).elseне выполняется, потому что подходящая ветка уже найдена.- В консоли будет строка
x больше 5, но не больше 15.
Важно отметить, что ветви elif и else являются опциональными. Конструкция может состоять только из одного if.
Присваивание в условии (:=)
С Python 3.8 в условии if или заголовке while можно присвоить значение переменной и сразу проверить его — оператор := (walrus, "моржовый"). Определение и синтаксис — в Работа с типами — операторы.
В if — сохранить длину списка и сразу сравнить:
data = list(range(12))
if (n := len(data)) > 10:
print(f"{n} items")
Разбор:
len(data)вычисляется один раз, результат попадает вn.- Условие
(n := len(data)) > 10истинно, печатается12 items. - Без walrus пришлось бы писать две строки:
n = len(data)иif n > 10:.
В while — читать ввод и проверять его в одном выражении:
while (line := input("Enter: ")) != "quit":
print("You typed:", line)
Разбор:
- Каждая итерация вызывает
input(...), строка сохраняется вline. - Цикл продолжается, пока пользователь не введёт
quit. - Переменная
lineдоступна в теле цикла на каждой итерации.
Скобки вокруг (n := len(data)) и (line := input(...)) нужны из-за приоритета операторов.
Сопоставление с образцом (match / case, Python 3.10+)
Конструкция match — альтернатива длинным цепочкам if/elif, когда нужно разобрать структуру значения (число, строка, кортеж, объект):
def http_status_line(code: int) -> str:
match code:
case 200:
return "OK"
case 404:
return "Not Found"
case 500 | 502 | 503:
return "Server error"
case n if 400 <= n < 500:
return f"Client error {n}"
case _:
return "Unknown"
case _ — ветка по умолчанию (как else). Для простых двух вариантов по-прежнему достаточно if/else; match удобен при многих ветках и распаковке структур. Ключевые слова перечислены в справочнике ключевых слов.
if <условие>:
<действие>
if <условие>:
<действие_1>
else:
<действие_2>
if <условие_1>:
<действие_1>
elif <условие_2>:
<действие_2>
else:
<действие_3>
Логические операторы
Логические операторы используются для комбинирования или инвертирования булевых выражений. В Python они представлены словами and, or, not, в отличие от многих других языков программирования, где применяются символьные аналоги (&&, ||, !). Это делает код более читаемым, но требует внимания при сравнении с другими C-подобными языками.
and— возвращает True, если оба операнда истинны.or— возвращает True, если хотя бы один операнд истинен.not— возвращает логическое отрицание операнда.
<выражение_1> and <выражение_2>
<выражение_1> or <выражение_2>
not <выражение>
Операторы работают по принципу короткого замыкания (short-circuit evaluation):
xandy: если x ложно, y не вычисляется.xory: если x истинно, y не вычисляется.
Пример:
a = True
b = False
print(a and b) # False
print(a or b) # True
print(not a) # False
Разбор примера:
andвозвращаетTrueтолько если оба операнда истинны.True and FalseдаётFalse.orвозвращаетTrue, если истинен хотя бы один операнд.True or FalseдаётTrue.notинвертирует булево значение.not TrueдаётFalse.print(...)выводит результат каждой операции в отдельной строке.
Такой подход позволяет эффективно управлять порядком вычислений и избегать ошибок, например:
if obj is not None and obj.has_method():
obj.method()
Здесь has_method() не будет вызван, если obj — None, поскольку первая часть условия ложна, и вторая не вычисляется.
Важно не путать логические операторы с операторами сравнения:
==равно;!=не равно;>больше;<меньше;>=больше или равно;<=меньше или равно.
Сравнительные операторы
Есть классические операторы сравнения:
Код ITЗагрузка примера кода…
Операторы is и == выполняют разные типы сравнения, что важно понимать для корректной работы с объектами.
== — проверяет равенство значений двух объектов. Вызывает метод __eq__() соответствующего класса.
is — проверяет идентичность объектов, то есть указывают ли две переменные на один и тот же объект в памяти (сравнивает их идентификаторы через id()).
<значение_1> == <значение_2>
<значение_1> != <значение_2>
<значение_1> > <значение_2>
<значение_1> < <значение_2>
<значение_1> >= <значение_2>
<значение_1> <= <значение_2>
<объект_1> is <объект_2>
<объект> is None
Пример:
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True — значения одинаковы
print(a is b) # False — это разные объекты в памяти
Разбор примера:
aиbсодержат одинаковые элементы, поэтомуa == bвозвращаетTrue.a is bсравнивает не значения, а идентичность объектов.- В памяти созданы два разных списка, поэтому
a is bвозвращаетFalse. - Практическое правило: для сравнения данных используйте
==, аisоставляйте дляNoneи синглтонов.
Однако:
c = a
print(a is c) # True — c ссылается на тот же объект, что и a
Разбор примера:
c = aне копирует список, а создаёт второе имя для того же объекта.- Поэтому
a is cвозвращаетTrue. - Если изменить
a, изменения будут видны и черезc.
Исключение составляют малые целые числа и строки, которые интернируются (кэшируются) интерпретатором. Например:
x = 256
y = 256
print(x is y) # True (в большинстве реализаций)
x = 257
y = 257
print(x is y) # Может быть False — зависит от контекста выполнения
По этой причине не рекомендуется использовать is для сравнения значений, особенно числовых или строковых. Оператор is следует применять в основном для сравнения с None, True, False и другими синглтонами:
if obj is None:
print("Объект не определён")
Это считается лучшей практикой, поскольку None — уникальный объект.
Интерактивное демо — пошаговый цикл на примере JavaScript (
for,while). В Python синтаксис другой (for…in,while), но порядок шагов тот же. Обобщённо: циклы в коде.
Play ITЗагрузка интерактивного демо…
Циклы
В Python два основных оператора повторения — for … in (обход итерируемого) и while (пока условие истинно). Оператора do…while в языке нет; "сделать хотя бы раз" имитируют через while True с break или отдельной проверкой после первого прохода.
| Конструкция | Порядок | Когда удобна |
|---|---|---|
for … in | следующий элемент → тело | список, строка, range(), ключи словаря, генератор |
| списковое включение | выражение → элемент → … | новый список из итерируемого за одну строку |
while | проверка условия → тело | число итераций заранее неизвестно |
Счётный цикл "N раз" в Python обычно пишут как for i in range(N) или for _ in range(N), а не через while со счётчиком. Обобщённая теория — циклы в коде.
for
Цикл for в Python является итерационным, а не счётным, как в некоторых других языках. Он предназначен для обхода элементов итерируемого объекта — коллекций, строк, диапазонов и других объектов, поддерживающих протокол итерации.
Синтаксис:
for переменная in итерируемый_объект:
# тело цикла
Часто в качестве итерируемого объекта используется функция range(), которая генерирует арифметическую последовательность чисел.
Функция range(stop) — создаёт объект диапазона, содержащий целые числа от 0 до stop - 1.
range(start, stop[, step]) позволяет задать начальное значение, конечное значение (не включая его) и шаг.
Примеры:
Код ITЗагрузка примера кода…
Разбор примера:
for i in range(10)выполняет тело 10 раз, аiпринимает значения от0до9.print(i, end=" ")печатает числа в одну строку, разделяя их пробелом.range(0, 50, 5)задаёт начало, конец (не включая 50) и шаг 5.range(10, 0, -1)использует отрицательный шаг и даёт обратный отсчёт.for letter in 'word'итерируется по строке посимвольно —w,o,r,d.
Обратите внимание — range() возвращает объект типа range, который является ленивым (lazy) — числа генерируются по мере необходимости, что экономит память.
Я бы выделил три основных вида цикла for():
for(A)- повторять определённое количество раз;for(A, B)- выполнять количество раз в диапазоне отAдоB;for(A, B, C)- выполнять количество раз в диапазоне отAдоB, с размером шагаC.
Цикл for можно использовать с любыми итерируемыми типами:
- списками;
- кортежами;
- множествами;
- словарями (ключи);
- генераторами;
- т.д.
for <переменная> in <итерируемый_объект>:
<действие>
for <переменная> in range(<конец>):
<действие>
for <переменная> in range(<начало>, <конец>):
<действие>
for <переменная> in range(<начало>, <конец>, <шаг>):
<действие>
К примеру, повторить 100 раз какую-то фразу:
for i in range(100):
print(f'{i}. Повтор!')
Комбинированные паттерны
# Поиск с прерыванием
for <элемент> in <коллекция>:
if <условие_нахождения>:
<обработка>
break
# Пропуск элементов
for <элемент> in <коллекция>:
if <условие_пропуска>:
continue
<обработка>
# Безопасная проверка объекта
if <объект> is not None and <объект>.<метод>():
<действие>
# Итерация по словарю
for <ключ> in <словарь>:
<действие_с_ключом>
for <ключ>, <значение> in <словарь>.items():
<действие_с_парой>
Списковые включения — «for в одну строку»
Списковое включение (list comprehension) — компактная запись цикла for, который сразу строит новый список. В разговорной речи его иногда называют «генератором списка», но не путайте с функцией-генератором (yield) и выражением-генератором в круглых скобках — об этом ниже и в статье Итераторы, генераторы и контекстные менеджеры.
Вместо «создать пустой список → пройти циклом → append» вы описываете результат одним выражением. Это один из самых характерных приёмов Python — от простых квадратов чисел до генерации игровых карт и матриц.
Полный синтаксис
[<выражение> for <элемент> in <итерируемый_объект> if <условие>]
Читаем слева направо: сначала что попадёт в список, затем откуда берутся элементы, при необходимости — фильтр в конце.
[x ** 2 for x in range(5)]
# ^^^^^ ^^^^^^^^^^^^^^^
# что откуда берём
# делаем элементы
Часть if <условие> необязательна. Без неё перебираются все элементы итератора.
Базовые формы
# 1. Простое включение — без преобразования
[x for x in range(10)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 2. С преобразованием
[x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 3. С фильтрацией
[x for x in range(10) if x % 2 == 0]
# [0, 2, 4, 6, 8]
# 4. Фильтрация и преобразование вместе
[x ** 2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]
Эквивалент четвёртой формы через обычный цикл:
result = []
for x in range(10):
if x % 2 == 0:
result.append(x ** 2)
Тот же шаблон работает со строками, списками и любыми итерируемыми объектами:
upper = [letter.upper() for letter in "hello"]
lengths = [len(word) for word in ["Python", "Java", "Go"]]
Условное выражение внутри включения
Если в список должны попадать разные значения в зависимости от условия, в левую часть (в <выражение>) вставляют тернарный оператор:
<значение_если_True> if <условие> else <значение_если_False>
result = [x if x % 2 == 0 else -x for x in range(10)]
# [0, -1, 2, -3, 4, -5, 6, -7, 8, -9]
# чётные оставляем, нечётные делаем отрицательными
Разбор:
for x in range(10)— источник элементов.x if x % 2 == 0 else -x— выражение результата для каждогоx.- Фильтрующий
ifв конце здесь не нужен — в список попадают все десять чисел, просто в разном виде.
Типичный приём в roguelike и тайловых играх — карта с границей-стеной:
ROWS, COLS = 10, 15
map_with_border = [
['#' if x == 0 or x == COLS - 1 or y == 0 or y == ROWS - 1 else '.'
for x in range(COLS)]
for y in range(ROWS)
]
# края — стены ('#'), внутри — пол ('.')
Внешний цикл for y in range(ROWS) строит строки карты, внутренний — столбцы в каждой строке. Похожие приёмы — в практикуме по roguelike.
Вложенные включения
Вложенное включение — это включение, результат которого снова используется как элемент другого включения. Внешний цикл for идёт последним в записи (снизу вверх при чтении).
Матрица одинаковых строк:
matrix = [[j for j in range(3)] for i in range(3)]
# [[0, 1, 2], [0, 1, 2], [0, 1, 2]]
Матрица с уникальными значениями:
matrix = [[i * 3 + j for j in range(3)] for i in range(3)]
# [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
Транспонирование (строки становятся столбцами):
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Шахматная доска — чередование символов по сумме координат:
chess_board = [
['♖' if (x + y) % 2 == 0 else '♘' for x in range(8)]
for y in range(8)
]
Разворот (flatten) вложенного списка в один — один уровень вложенности, два цикла в одной строке:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Несколько циклов for в одном включении
Несколько for в одном включении эквивалентны вложенным циклам. Порядок сохраняется — как если бы вы писали for снаружи внутрь:
# Обычный вложенный цикл
pairs = []
for x in range(3):
for y in range(3):
pairs.append((x, y))
# То же через включение
pairs = [(x, y) for x in range(3) for y in range(3)]
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Фильтр if в конце относится ко всей комбинации циклов:
# только пары, где x != y
pairs = [(x, y) for x in range(3) for y in range(3) if x != y]
# [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
# пары с суммой координат 3
pairs = [(x, y) for x in range(4) for y in range(4) if x + y == 3]
# [(0, 3), (1, 2), (2, 1), (3, 0)]
Несколько if подряд работают как цепочка and:
result = [x for x in range(20) if x % 2 == 0 if x % 3 == 0]
# [0, 6, 12, 18] — делятся и на 2, и на 3
Включения для set и dict
Тот же синтаксис «цикл + выражение» работает для других коллекций:
| Конструкция | Скобки | Результат |
|---|---|---|
| списковое включение | [...] | list |
| включение множества | {expr ...} (без :) | set |
| словарное включение | {ключ: значение ...} | dict |
Множество — уникальные значения:
squares = {x ** 2 for x in range(10)}
letters = {char for char in "hello world" if char != ' '}
# {'h', 'e', 'l', 'o', 'w', 'r', 'd'}
Словарь — пары ключ–значение:
squares_dict = {x: x ** 2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
original = {'a': 1, 'b': 2, 'c': 3}
inverted = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b', 3: 'c'}
filtered = {k: v for k, v in original.items() if v > 1}
# {'b': 2, 'c': 3}
Подробнее про включения в контексте коллекций — в главе Типы данных.
enumerate, zip и другие итераторы
Включение не обязано идти только по range() — источником может быть любой итерируемый объект:
# индекс + значение
indexed = [(i, x) for i, x in enumerate(['a', 'b', 'c'])]
# [(0, 'a'), (1, 'b'), (2, 'c')]
# параллельный обход двух списков
names = ['Alice', 'Bob', 'Charlie']
scores = [85, 92, 78]
students = [(name, score) for name, score in zip(names, scores)]
# [('Alice', 85), ('Bob', 92), ('Charlie', 78)]
Функции enumerate и zip — в статье Функции.
Примеры из игровой логики
Клетки комнаты — все координаты прямоугольника одним выражением:
def create_room(x, y, w, h):
room_cells = [(cx, cy) for cx in range(x, x + w) for cy in range(y, y + h)]
for cx, cy in room_cells:
game_map[cy][cx] = '.' # пол комнаты
Видимые клетки в радиусе (круг на дискретной сетке):
visible_cells = [
(x, y)
for x in range(max(0, px - radius), min(COLS, px + radius + 1))
for y in range(max(0, py - radius), min(ROWS, py + radius + 1))
if (x - px) ** 2 + (y - py) ** 2 <= radius ** 2
]
Пакетное создание объектов — несколько монстров за один проход:
import random
monsters = [
Monster(
random.randint(room[0] + 1, room[0] + room[2] - 2),
random.randint(room[1] + 1, room[1] + room[3] - 2),
random.choice(['Goblin', 'Orc', 'Bat']),
random.randint(3, 8),
random.randint(1, 4),
)
for _ in range(random.randint(1, 3))
]
Фильтрация «живых» объектов после обновления:
particles = [p for p in particles if p.update()]
# update() двигает частицу и возвращает False, когда life <= 0
Система частиц — создание и отбор за два включения:
import random
class Particle:
def __init__(self, x, y, dx, dy):
self.x, self.y, self.dx, self.dy = x, y, dx, dy
self.life = 100
def update(self):
self.x += self.dx
self.y += self.dy
self.life -= 1
return self.life > 0
particles = [
Particle(
random.randint(0, 800),
random.randint(0, 600),
random.uniform(-1, 1),
random.uniform(-1, 1),
)
for _ in range(100)
]
particles = [p for p in particles if p.update()]
Выражение-генератор
Выражение-генератор выглядит как списковое включение, но в круглых скобках и не создаёт список сразу — возвращает ленивый итератор:
list_comp = [x ** 2 for x in range(1_000_000)] # list — всё в памяти
gen_exp = (x ** 2 for x in range(1_000_000)) # generator — по одному элементу
total = sum(x ** 2 for x in range(10)) # скобки часто опускают
Разница принципиальна:
[...]— все элементы материализуются сразу.(...)— элементы считаются по запросу (next, циклfor,sum,max).
В roguelike, если список координат нужен только для одного прохода, выгоднее не создавать список:
visible_cells = (
(x, y)
for x in range(max(0, px - radius), min(COLS, px + radius + 1))
for y in range(max(0, py - radius), min(ROWS, py + radius + 1))
if (x - px) ** 2 + (y - py) ** 2 <= radius ** 2
)
for x, y in visible_cells:
game_map[y][x].visible = True
Когда нужен именно список (индексация, повторный обход, len) — квадратные скобки. Когда достаточно одного прохода — круглые скобки или выражение без обёртки.
Когда включение, когда обычный for
Удобно, когда:
- простое преобразование:
squares = [x ** 2 for x in numbers]; - фильтрация:
evens = [x for x in numbers if x % 2 == 0]; - создание матрицы:
matrix = [[0 for _ in range(cols)] for _ in range(rows)]; - код читается как «создать список из…».
Лучше обычный for, когда:
# 1. Сложная логика с несколькими ветками
# Плохо:
result = [x if x > 0 else y if y > 0 else z for x, y, z in zip(a, b, c)]
# Хорошо:
result = []
for x, y, z in zip(a, b, c):
if x > 0:
result.append(x)
elif y > 0:
result.append(y)
else:
result.append(z)
# 2. Побочные эффекты (print, запись в файл, API)
# Плохо:
[print(x) for x in range(5)]
# Хорошо:
for x in range(5):
print(x)
# 3. Очень большой объём и один проход — генераторное выражение
# list: [x for x in range(1_000_000)]
# gen: (x for x in range(1_000_000))
Списковое включение — выражение, возвращающее список; цикл for — оператор с блоком инструкций.
Производительность
Списковые включения обычно быстрее эквивалентного цикла с append: интерпретатор выполняет построение списка на более низком уровне, без повторных вызовов метода.
import timeit
def test_loop():
result = []
for i in range(1000):
result.append(i ** 2)
return result
def test_comprehension():
return [i ** 2 for i in range(1000)]
# На типичной машине comprehension быстрее примерно на 30–50 %
timeit.timeit(test_loop, number=10_000)
timeit.timeit(test_comprehension, number=10_000)
Разница заметна на больших объёмах и в горячих участках кода. На читаемости экономить не стоит — если включение превращается в «однострочник на полэкрана», вернитесь к обычному for.
Полезные приёмы
Матрица без ловушки общей ссылки — [[0] * cols] * rows даёт один и тот же внутренний список во всех строках. Правильно:
# НЕЛЬЗЯ: [[0, 0]] * 3 — все строки ссылаются на один список
matrix = [[0 for _ in range(cols)] for _ in range(rows)]
Подсчёт вхождений через включение (для небольших данных; на больших — collections.Counter):
words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
counts = {word: words.count(word) for word in set(words)}
# {'apple': 3, 'banana': 2, 'orange': 1}
Безопасное удаление из списка — не менять коллекцию во время обхода, а собрать новую:
items = [1, 2, 3, 4, 5]
items = [x for x in items if x % 2 == 1]
# [1, 3, 5]
Тот же приём — в разделе Частые ловушки ниже.
Частые ошибки
Забытый if — условие фильтрации пишется только с ключевым словом if:
# Ошибка:
# [x for x in range(10) x % 2 == 0]
# Правильно:
[x for x in range(10) if x % 2 == 0]
Порядок циклов — переменная в <выражение> должна быть объявлена раньше (левее) того цикла, где используется:
# Ошибка — x ещё не определён в момент чтения выражения:
# [x for y in range(3) for x in range(2)]
# Правильно:
[x for x in range(2) for y in range(3)]
Путаница «изменить» и «создать новый» — включение не меняет исходный список, а возвращает новый. Результат нужно присвоить переменной:
numbers = [1, 2, 3, 4, 5]
doubled = [x * 2 for x in numbers] # numbers не изменился
numbers = doubled # явная замена — ок
Вложенное включение для побочных эффектов — [game_map[y].__setitem__(x, '.') for ...] и подобное лучше заменить обычным for: включение должно возвращать данные, а не выполнять действия ради действий.
while
Цикл while выполняет блок кода до тех пор, пока указанное условие остаётся истинным. Он используется, когда количество итераций заранее неизвестно.
Синтаксис:
while условие:
# тело цикла
Пример:
count = 0
while count < 5:
print(count)
count += 1
Разбор примера:
count = 0задаёт начальное значение счётчика.- Перед каждой итерацией проверяется условие
count < 5. - Внутри цикла текущее значение выводится в консоль.
count += 1изменяет состояние, поэтому цикл в итоге завершается.- Результат вывода: числа от
0до4.
Типичный приём с walrus — чтение ввода прямо в условии цикла (см. присваивание в условии):
while (line := input("Enter: ")) != "quit":
print("You typed:", line)
while <условие>:
<действие>
Важно обеспечить выход из цикла, иначе он станет бесконечным. Бесконечный цикл возникает, если условие никогда не становится ложным:
while True:
print("Это бесконечный цикл")
Такие конструкции допустимы, если внутри цикла предусмотрен механизм прерывания через break.
Для детального контроля над выполнением циклов и условных блоков в Python предусмотрены специальные управляющие инструкции.
break — немедленно прекращает выполнение текущего цикла и передаёт управление следующему за ним блоку кода. Часто используется при поиске элемента или обработке ошибок.
for i in range(10):
if i == 5:
break
print(i) # Вывод: 0, 1, 2, 3, 4
Разбор примера:
- Цикл идёт по числам от
0до9. - Когда
iстановится5, срабатываетbreak. breakмгновенно завершает весь цикл, а не только текущую итерацию.- Поэтому печатаются только
0, 1, 2, 3, 4. continue — прерывает текущую итерацию и переходит к следующей. Управление возвращается к началу цикла, где проверяется условие.
for i in range(5):
if i == 2:
continue
print(i) # Вывод: 0, 1, 3, 4
Разбор примера:
continueпропускает оставшийся код текущей итерации.- При
i == 2вызовprint(i)не выполняется. - Цикл продолжается со следующего значения.
- Поэтому в выводе отсутствует только
2.
pass — пустая операция. Используется как заглушка, когда синтаксически требуется наличие инструкции, но логика ещё не реализована.
if condition:
pass # Заглушка для будущей реализации
else:
print("Условие ложно")
pass также применяется в определениях классов, функций и блоков, где отсутствие кода привело бы к синтаксической ошибке.
Связанные материалы
- Сопоставление с образцом (match / case) — ветвление по структуре данных (Python 3.10+)
- Типы данных — списковые и словарные включения
- Итераторы, генераторы и контекстные менеджеры — выражения-генераторы,
yield, ленивые вычисления - Функции
- Обработка исключений
Практическая логика написания условий и циклов
Чтобы код оставался читаемым при росте проекта, полезно придерживаться трёх правил:
- Условия пишутся от "самого узкого и критичного" к "общему".
- Длинные проверки выносятся в отдельные функции-предикаты.
- Цикл отвечает за обход, а бизнес-логика выносится в функции.
Пример аккуратного предиката:
def can_publish(post, user):
return user.is_staff and post.is_ready and not post.is_archived
if can_publish(post, user):
publish(post)
Так код проще тестировать и поддерживать.
Частые ловушки новичков
- Ошибочный
isвместо==при сравнении строк и чисел. - Изменение коллекции во время обхода той же коллекции в
for— безопаснее собрать новый список через списковое включение. - Бесконечный
whileиз-за условия, которое не меняется. - Глубокие вложенные
if, где лучше ранний выход черезreturn. - Включение ради побочного эффекта —
[print(x) for x in items]вместо обычногоfor(см. когда не использовать включение). [[0] * cols] * rowsвместо[[0 for _ in range(cols)] for _ in range(rows)]— общая ссылка на внутренние списки.
Безопасный шаблон изменения списка:
items = [1, 2, 3, 4, 5]
items = [x for x in items if x % 2 == 1]
Это надёжнее, чем удалять элементы из items внутри цикла.