Условия: как программа принимает решения
До сих пор наши программы были похожи на список поручений: сделай раз, сделай два, сделай три — и всегда одинаково. Такая программа полезна, но она не умеет главного: реагировать. Настоящие программы всё время что-то решают. Пароль подошёл или нет? Товара хватает на складе или нет? Пользователь совершеннолетний или нет? От ответа зависит, что произойдёт дальше.
Механизм, который отвечает за такие развилки, называется условием (по-английски conditional). В Python он записывается словами if, elif и else. Это, пожалуй, первая по-настоящему «умная» конструкция, которую вы изучите — и одна из тех, которыми вы будете пользоваться каждый день до конца карьеры.
Мы будем опираться на переменные и типы данных из статьи Переменные и типы данных. Если что-то из неё забылось — ничего страшного, я буду напоминать по ходу.
Аналогия: развилка на дороге
Представьте, что вы идёте по тропинке и доходите до развилки. Рядом стоит табличка: «Если идёт дождь — сворачивай направо, к навесу. Иначе — иди прямо, через поле». Вы смотрите на небо, отвечаете себе «да» или «нет» и идёте по одной из двух троп. Потом обе тропы снова сходятся, и вы продолжаете путь.
Условие в программе устроено ровно так же:
- есть вопрос, на который можно ответить только «да» или «нет» (идёт ли дождь);
- есть ветка на случай «да»;
- есть (не обязательно) ветка на случай «нет»;
- после развилки программа продолжает работу как ни в чём не бывало.
сверху вниз"] --> B{"Идёт дождь?"} B -- "да" --> C["Свернуть к навесу"] B -- "нет" --> D["Идти через поле"] C --> E["Продолжаем путь"] D --> E
Где аналогия ломается. На реальной развилке вы можете постоять, подумать, вернуться назад. Программа так не умеет: она проверяет условие ровно один раз, мгновенно выбирает ветку и идёт дальше. Вернуться и «переиграть» решение она не может — если только вы сами не напишете такую логику. Ещё важно: программа не понимает «наверное» или «почти». Ответ строго один из двух.
«Да» и «нет» на языке программы: тип bool
Чтобы задать вопрос, нужен способ записать ответ. В Python для этого есть отдельный тип данных — bool (читается «бул», от фамилии математика Джорджа Буля). У него всего два возможных значения:
True— истина, «да»;False— ложь, «нет».
Пишутся они с большой буквы и без кавычек. true (с маленькой) Python не поймёт, а "True" в кавычках — это уже обычный текст, а не истина.
is_raining = True # переменная хранит "да"
is_sunny = False # переменная хранит "нет"
print(is_raining) # выведет: True
print(type(is_sunny)) # выведет: <class 'bool'>
Ожидаемый вывод:
True
<class 'bool'>
type(...) — это встроенная команда, которая сообщает тип значения. <class 'bool'> означает «это булево значение».
Откуда берутся True и False: операторы сравнения
Вручную писать True приходится редко. Обычно ответ вычисляется — из сравнения двух значений. Операторов сравнения шесть:
| Оператор | Читается как | Пример | Результат |
|---|---|---|---|
== |
равно | 5 == 5 |
True |
!= |
не равно | 5 != 3 |
True |
> |
больше | 2 > 7 |
False |
< |
меньше | 2 < 7 |
True |
>= |
больше или равно | 7 >= 7 |
True |
<= |
меньше или равно | 9 <= 4 |
False |
Обратите внимание на два знака равенства в проверке равенства. Это не опечатка и не прихоть — это важнейшее различие, которое подводит почти каждого новичка:
=— присваивание: «положи это значение в переменную». Команда.==— сравнение: «а эти два значения одинаковые?». Вопрос.
age = 18 # присваиваем: в переменной age теперь 18
print(age == 18) # спрашиваем: а age равно 18? -> True
print(age == 21) # спрашиваем: а age равно 21? -> False
print(age != 21) # спрашиваем: а age НЕ равно 21? -> True
Вывод:
True
False
True
Сравнивать можно не только числа. Строки сравниваются на равенство буква в букву, с учётом регистра:
password = "Kitten"
print(password == "Kitten") # True
print(password == "kitten") # False — большая К и маленькая к это разные символы
Первое настоящее условие: if
Теперь соберём всё вместе. Синтаксис (то есть правила записи) минимальный:
temperature = 30
if temperature > 25:
print("Жарко, пей воду")
print("Программа продолжается")
Вывод:
Жарко, пей воду
Программа продолжается
Разберём построчно:
temperature = 30— создаём переменную и кладём в неё число 30.if temperature > 25:— словоif(«если»), затем условие, затем двоеточие. Python вычисляетtemperature > 25, получаетTrue.print("Жарко, пей воду")— строка сдвинута вправо на четыре пробела. Этот сдвиг называется отступ (indent). Отступ означает: «эта строка принадлежит условию сверху». Раз условие истинно — строка выполняется.- Пустая строка — просто для читаемости, на работу не влияет.
print("Программа продолжается")— отступа нет, значит строка не принадлежит условию. Она выполнится в любом случае.
Поменяйте temperature = 30 на temperature = 10 и запустите снова. Вывод станет таким:
Программа продолжается
Первая строка исчезла — условие оказалось ложным, и Python просто перепрыгнул через её блок.
Отступы — это синтаксис, а не оформление
Во многих языках блоки кода обозначают фигурными скобками, а отступы делают «для красоты». В Python отступ сам по себе является границей блока. Это первое, что нужно принять и запомнить.
Практические правила:
- Стандартный отступ — 4 пробела. Не 2, не 3, не 8. Так принято, и так делает почти весь мир Python.
- Не смешивайте пробелы и табуляцию. Внешне они выглядят одинаково, а Python считает их разными и ругается. Нормальный редактор кода (VS Code, PyCharm) по умолчанию превращает Tab в 4 пробела — это то, что нужно.
- Все строки одного блока должны иметь одинаковый отступ.
Официальное описание — в стандарте оформления кода PEP 8, это главный документ о том, как принято писать на Python.
Вторая ветка: else
else («иначе») — это блок, который выполнится, если условие оказалось ложным. Ровно одна из двух веток сработает всегда: и обе одновременно — никогда.
age = 15
if age >= 18:
print("Доступ разрешён")
else:
print("Доступ запрещён: нужно 18 лет")
print("Проверка завершена")
Вывод:
Доступ запрещён: нужно 18 лет
Проверка завершена
Заметьте: у else нет собственного условия. Он не спрашивает «а если наоборот?» — он просто ловит все остальные случаи. Поэтому после else сразу идёт двоеточие, и никаких сравнений между ними быть не может.
Больше двух вариантов: elif
Жизнь редко делится надвое. Оценка бывает отличной, хорошей, средней и плохой. Для таких случаев есть elif — сокращение от else if, «иначе если».
score = 73
if score >= 90:
grade = "отлично"
elif score >= 75:
grade = "хорошо"
elif score >= 60:
grade = "удовлетворительно"
else:
grade = "неудовлетворительно"
print("Оценка:", grade)
Вывод:
Оценка: удовлетворительно
Вот что здесь критически важно понять — и это самое частое место, где новички путаются.
Python проверяет условия сверху вниз и останавливается на первом истинном. Все остальные ветки после этого пропускаются, даже если они тоже были бы истинны.
Проследим за score = 73:
score >= 90? 73 не больше и не равно 90 →False, идём дальше.score >= 75? 73 меньше 75 →False, идём дальше.score >= 60? 73 больше 60 →True! Присваиваемgrade = "удовлетворительно"и выходим из всей конструкции.elseне выполняется — до него дело уже не дошло.
Из этого следует практический вывод: порядок веток имеет значение. Если переставить условия от меньшего к большему, всё сломается:
score = 95
if score >= 60: # 95 >= 60 -> True, срабатывает первая же ветка!
grade = "удовлетворительно"
elif score >= 90: # сюда никогда не попадём
grade = "отлично"
print(grade) # выведет: удовлетворительно
Отличник получил тройку. Программа не сломалась и ошибку не показала — она честно сделала то, что написано. Такие ошибки называются логическими: код работает, но неправильно. Их искать сложнее всего, и о том, как это делать, есть отдельная статья — Ошибки и отладка.
Правило: в цепочке elif сначала пишите самые строгие (самые узкие) условия, потом более широкие.
Сколько может быть веток
if— обязателен и ровно один.elif— сколько угодно, включая ноль.else— не более одного, и всегда последним.
Соединяем несколько вопросов: and, or, not
Часто решение зависит не от одного факта, а от нескольких сразу. Для этого есть три логических оператора. В Python они называются человеческими словами:
and («и») — истина, только если истинны оба условия.
age = 25
has_ticket = True
if age >= 18 and has_ticket:
print("Проходите в зал")
else:
print("Вход невозможен")
Вывод: Проходите в зал. Стоит хоть одному условию стать ложным — сработает else.
or («или») — истина, если истинно хотя бы одно условие.
day = "суббота"
if day == "суббота" or day == "воскресенье":
print("Выходной!")
else:
print("Рабочий день")
Вывод: Выходной!
Здесь легко ошибиться и написать if day == "суббота" or "воскресенье":. Так делать нельзя — Python не поймёт это как «или воскресенье». Ниже, в разделе про ошибки, разберём, почему.
not («не») — переворачивает ответ: истину делает ложью и наоборот.
is_banned = False
if not is_banned:
print("Добро пожаловать")
Вывод: Добро пожаловать. Читается почти как английская фраза: «если не забанен».
Таблица истинности
Полный список исходов удобно держать перед глазами:
| A | B | A and B |
A or B |
not A |
|---|---|---|---|---|
True |
True |
True |
True |
False |
True |
False |
False |
True |
False |
False |
True |
False |
True |
True |
False |
False |
False |
False |
True |
Ленивая проверка: Python не делает лишней работы
Ещё одна деталь, которая позже вас выручит. Если в A and B левая часть оказалась ложной, результат уже определён — он точно False. Правую часть Python даже не станет вычислять. То же с or: если левая часть истинна, правую он пропустит. Это называется короткое замыкание (short-circuit evaluation).
B не вычисляется вообще"] B -- "да" --> D["Вычисляем B"] D --> E["Ответ равен B"] F["Вычисляем: A or B"] --> G{"A истинно?"} G -- "да" --> H["Ответ True.
B не вычисляется вообще"] G -- "нет" --> I["Вычисляем B"] I --> J["Ответ равен B"]
Зачем это знать? Потому что порядок в and может защитить от ошибки:
name = ""
# Сначала проверяем, что строка не пустая, и только потом лезем в её первый символ
if name != "" and name[0] == "А":
print("Имя начинается на А")
else:
print("Не подходит")
Если поменять части местами, программа упадёт на пустой строке: обращение к первому символу несуществующего текста — ошибка. Благодаря короткому замыканию порядок «сначала безопасная проверка, потом рискованная» работает надёжно.
Условия внутри условий
Блок if может содержать внутри себя другой if — это называется вложенностью. Отступ у вложенного блока удваивается.
is_logged_in = True
is_admin = False
if is_logged_in:
print("Вы вошли в систему")
if is_admin:
print("Открыта панель администратора")
else:
print("Обычный пользователь")
else:
print("Пожалуйста, войдите")
Вывод:
Вы вошли в систему
Обычный пользователь
Вложенность работает, но злоупотреблять ею не стоит: после трёх-четырёх уровней код превращается в «лесенку», в которой невозможно разобраться. Часто вложенность можно заменить на and:
# Три уровня вложенности — тяжело читать
if is_logged_in:
if is_admin:
if not is_banned:
print("Панель администратора")
# То же самое одной строкой — гораздо понятнее
if is_logged_in and is_admin and not is_banned:
print("Панель администратора")
Выбирайте вложенность, только когда в промежуточных ветках действительно есть свои действия или свой else.
Что Python считает «истинным» само по себе
Внутри if можно писать не только сравнение, но и просто значение. Python сам решит, считать его истиной или ложью. Правило простое: «пусто и ноль» — ложь, всё остальное — истина.
Ложными считаются: False, 0, 0.0, пустая строка "", пустой список [], пустой словарь {} и None (специальное значение «ничего»).
name = input("Как вас зовут? ")
if name: # то же самое, что name != ""
print("Привет,", name)
else:
print("Вы не ввели имя")
Если пользователь просто нажмёт Enter, name окажется пустой строкой — а значит, ложью, и сработает else.
Пользоваться этим удобно, но с осторожностью: if count: и if count > 0: ведут себя одинаково для положительных чисел, но по-разному, если count может быть отрицательным. Когда сомневаетесь — пишите сравнение явно. Явное лучше неявного, это буквально первая строка «Дзена Python».
Типичные ошибки новичков и что означают сообщения
Сообщения об ошибках пугают, потому что написаны по-английски и выглядят как ругань. На самом деле Python довольно вежливо объясняет, что не так. Разберём самые частые случаи дословно.
1. Забыли двоеточие
if age > 18
print("ok")
SyntaxError: expected ':'
Дословно: «синтаксическая ошибка: ожидалось двоеточие». Python дочитал условие до конца строки и не нашёл :. Лечится добавлением двоеточия.
2. Забыли отступ
if age > 18:
print("ok")
IndentationError: expected an indented block after 'if' statement on line 1
Дословно: «ошибка отступа: ожидался блок с отступом после инструкции if в строке 1». Python увидел if, ждал тело — а тело написано вплотную к краю. Сдвиньте строку на 4 пробела.
3. Написали = вместо ==
if age = 18:
print("ровно 18")
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
Python прямо подсказывает: «может быть, вы имели в виду ==?». Да, именно это вы и имели в виду. Присваивать внутри if нельзя — там должен быть вопрос, а не команда.
4. Сравнили строку с числом
age = input("Сколько вам лет? ") # input ВСЕГДА возвращает строку
if age >= 18:
print("совершеннолетний")
TypeError: '>=' not supported between instances of 'str' and 'int'
Дословно: «ошибка типа: оператор >= не поддерживается между значениями типа str (строка) и int (целое число)». Python не знает, как сравнить текст "18" с числом 18 — для него это разные сущности, как сравнивать длину с весом.
Это, возможно, ошибка №1 у всех новичков. Лечится преобразованием типа:
age = int(input("Сколько вам лет? ")) # int(...) превращает строку в число
if age >= 18:
print("совершеннолетний")
else:
print("несовершеннолетний")
5. or с двумя значениями вместо двух условий
day = "среда"
if day == "суббота" or "воскресенье":
print("Выходной!")
Вывод: Выходной! — хотя среда точно не выходной. Ошибки нет, но результат неверный.
Почему так? Python читает это как (day == "суббота") or ("воскресенье"). Первая часть — False. Вторая часть — непустая строка, а непустая строка считается истиной (см. раздел выше). False or True даёт True. Программа отработала строго по правилам — просто вы попросили не то, что хотели.
Правильно — повторить сравнение полностью:
if day == "суббота" or day == "воскресенье":
Или использовать проверку на вхождение в набор — оператор in, который читается как «содержится в»:
if day in ("суббота", "воскресенье"):
print("Выходной!")
6. Избыточное сравнение с True
if is_admin == True: # работает, но многословно
if is_admin: # так пишут опытные разработчики
is_admin уже является ответом «да/нет» — сравнивать его с True всё равно что спрашивать «правда ли, что правда?».
7. Сравнение дробных чисел на равенство
print(0.1 + 0.2 == 0.3) # выведет: False
Это не баг Python и не ваша ошибка. Компьютер хранит дробные числа приблизительно (подробности — в статье Как устроен компьютер), и 0.1 + 0.2 даёт 0.30000000000000004. Поэтому дробные числа сравнивают не на точное равенство, а на «достаточную близость»:
result = 0.1 + 0.2
if abs(result - 0.3) < 0.0000001: # abs(...) — модуль числа, расстояние до нуля
print("Считаем равными")
Приятная деталь: цепочки сравнений
В большинстве языков «число между 10 и 20» пишут через and. В Python можно писать как в математике — и это законно:
temperature = 15
if 10 <= temperature <= 20:
print("Комфортная температура")
Это полностью эквивалентно temperature >= 10 and temperature <= 20, просто читается легче. Пользуйтесь.
Собираем всё вместе: маленькая программа
Напишем классификатор возраста — короткий, но использующий всё, что мы прошли.
# Спрашиваем данные у пользователя и сразу превращаем текст в число
age = int(input("Введите ваш возраст: "))
# Отсекаем бессмысленный ввод — так делают в любой настоящей программе
if age < 0 or age > 130:
print("Похоже, вы ошиблись при вводе")
elif age < 7:
print("Дошкольник")
elif age < 18:
print("Школьник")
elif age < 65:
print("Взрослый")
else:
print("Пенсионный возраст")
print("Спасибо!")
Пример запуска:
Введите ваш возраст: 14
Школьник
Спасибо!
Ещё один запуск:
Введите ваш возраст: 200
Похоже, вы ошиблись при вводе
Спасибо!
Обратите внимание на первую ветку: проверка на «мусорный» ввод стоит раньше всех остальных. Это распространённый приём — сначала отсеять невозможное, потом разбирать нормальные случаи.
Практика
Задания идут от простого к сложному. Пишите каждое в отдельном файле и обязательно запускайте — понимание приходит от запуска, а не от чтения.
1. Чётное или нечётное
Попросите у пользователя целое число и сообщите, чётное оно или нечётное.
Подсказка: оператор % (он называется «остаток от деления») возвращает то, что осталось после деления. 10 % 2 даёт 0, а 7 % 2 даёт 1. Число чётное ровно тогда, когда остаток от деления на 2 равен нулю.
2. Больше, меньше или равно
Попросите два числа и выведите одну из трёх фраз: «первое больше», «второе больше» или «числа равны».
Подсказка: понадобится if, один elif и else. Подумайте, какая ветка может быть else — та, для которой уже не нужна отдельная проверка.
3. Пускатель в кино
Спросите возраст зрителя и возрастное ограничение фильма (два числа). Пустите зрителя, если возраст не меньше ограничения. Отдельно обработайте случай, когда ограничение — 0: тогда пускать нужно всех, и сообщение должно быть другим: «Фильм для всей семьи».
Подсказка: самое узкое условие — «ограничение равно нулю». Куда его поставить в цепочке?
4. Простой калькулятор
Спросите два числа и знак операции (+, -, *, /) отдельной строкой. Выполните нужное действие и выведите результат. Если знак не распознан — сообщите об этом.
Подсказка: знак операции — это строка, сравнивайте её через ==. И не забудьте про деление на ноль: перед делением проверьте, что второе число не равно нулю, иначе программа упадёт с ZeroDivisionError: division by zero.
5. Високосный год
Спросите год и определите, високосный ли он. Правило такое: год високосный, если он делится на 4, но не делится на 100 — кроме случая, когда он делится на 400 (тогда всё-таки високосный). Проверьте себя: 2024 — високосный, 1900 — нет, 2000 — да.
Подсказка: всё правило умещается в одно условие с and, or и not, но сначала попробуйте записать его вложенными if — так проще увидеть логику. Потом, когда заработает, попробуйте сократить. Это упражнение и на условия, и на аккуратность мышления.
Мини-итог
- Условие — это развилка: программа задаёт вопрос и в зависимости от ответа идёт по одной из веток.
- Ответ на вопрос — значение типа
bool:TrueилиFalse. =присваивает,==сравнивает. Их путают все, и все потом привыкают.- Отступ в Python — часть синтаксиса. Четыре пробела, единообразно, без табов вперемешку.
- В цепочке
if / elif / elseсрабатывает ровно одна ветка — первая подошедшая. Поэтому порядок условий важен: узкие проверки идут раньше широких. and,or,notсоединяют условия.andиorвычисляются лениво — это можно использовать для защиты от ошибок.- Ошибка
TypeError: '>=' not supported between instances of 'str' and 'int'почти всегда означает, что вы забыли обернутьinput()вint(). - Логическая ошибка страшнее синтаксической: программа не падает, а тихо делает не то. Проверяйте свои условия на крайних значениях.
Дополнительно почитать: раздел «More Control Flow Tools» в официальном учебнике Python и главу об условиях в Automate the Boring Stuff with Python Эла Свейгарта — книга бесплатно доступна онлайн и написана как раз для начинающих.
Что дальше
Теперь программа умеет выбирать. Следующий шаг — научить её повторять: обрабатывать сотню товаров, тысячу строк файла или каждую букву в слове, не переписывая один и тот же код сто раз. Этим занимаются циклы.