8. Принятие решений с помощью операторов if
В программах, которые мы писали до сих пор, Python выполняет каждую строку кода сверху вниз, одну инструкцию за другой. Но программам из реального мира нужно принимать решения — выполнять разный код в зависимости от разных условий. Должны ли мы показать сообщение об ошибке? Должны ли мы рассчитать скидку? Должны ли мы снова запросить ввод? Ответ зависит от ситуации.
Условные операторы (conditional statements) позволяют вашим программам принимать такие решения. Они позволяют Python выполнять определённые блоки кода только тогда, когда конкретные условия истинны, а иначе пропускать их. В этой главе рассматривается оператор if в Python и его варианты, которые составляют основу принятия решений в ваших программах.
Освоив условные операторы, вы сможете писать программы, которые разумно реагируют на ввод пользователя, корректно обрабатывают разные сценарии и решают задачи, требующие логических рассуждений.
8.1) Простые операторы if
Самая базовая форма принятия решений в Python — это простой оператор if. Он говорит Python: «Если это условие истинно, выполни этот блок кода. Иначе пропусти его и продолжай».
8.1.1) Структура оператора if
Вот базовый синтаксис оператора if:
if condition:
# Код, который нужно выполнить, если condition равно True
statement1
statement2
# ... больше операторовРазберём каждую часть:
- Ключевое слово
if: оно начинает условный оператор - Условие: булево выражение, которое вычисляется в
TrueилиFalse(из Главы 7) - Двоеточие (
:): оно обязательно и обозначает конец строки с условием - Блок кода с отступом: все инструкции с отступом под
ifвыполняются только когда условие равноTrue
Отступы критически важны в Python. Строки с отступом образуют блок кода, который относится к оператору if. Python использует отступы (обычно 4 пробела), чтобы определить, какие инструкции являются частью условного блока.
Вот простой пример:
# temperature_check.py
temperature = 30
if temperature > 25:
print("It's a warm day!")
print("Consider wearing light clothing.")
print("Have a great day!") # Это выполняется всегдаOutput:
It's a warm day!
Consider wearing light clothing.
Have a great day!В этом примере:
- Условие
temperature > 25вычисляется вTrue(поскольку 30 > 25) - Оба выражения
print()с отступом выполняются, потому что они входят в блокif - Последний
print()выполняется всегда, потому что он без отступа — он не является частью блокаif
Теперь посмотрим, что происходит, когда условие равно False:
# temperature_check_cool.py
temperature = 18
if temperature > 25:
print("It's a warm day!")
print("Consider wearing light clothing.")
print("Have a great day!") # Это выполняется всегдаOutput:
Have a great day!На этот раз:
- Условие
temperature > 25вычисляется вFalse(поскольку 18 не больше 25) - Оба выражения с отступом полностью пропускаются
- Выполняется только последний
print(), потому что он находится вне блокаif
8.1.2) Использование условий из Главы 7
Любое булево выражение из Главы 7 может быть использовано как условие в операторе if. Это включает:
Операторы сравнения:
# voting_eligibility.py
age = 16
if age >= 18:
print("You are eligible to vote.")
# Ничего не печатается, потому что 16 >= 18 равно False
score = 85
if score >= 60:
print("You passed the exam!") # Output: You passed the exam!Проверки принадлежности с in и not in:
# user_access.py
username = "alice"
banned_users = ["bob", "charlie", "dave"]
if username not in banned_users:
print(f"Welcome, {username}!") # Output: Welcome, alice!
favorite_color = "blue"
if "u" in favorite_color:
print("Your favorite color contains the letter 'u'.") # Output: Your favorite color contains the letter 'u'.Непосредственные булевы значения:
# weather_check.py
is_raining = True
if is_raining:
print("Don't forget your umbrella!") # Output: Don't forget your umbrella!Истинность и ложность (truthiness and falsiness) (из раздела 7.4):
# name_input.py
user_input = input("Enter your name: ")
if user_input: # Пустая строка — falsy, непустая — truthy
print(f"Hello, {user_input}!")
else:
print("You didn't enter a name.")8.1.3) Несколько инструкций в блоке if
Вы можете включать в блок if столько инструкций, сколько нужно. Все инструкции с отступом под строкой if относятся к этому блоку:
# bank_withdrawal.py
balance = 1500
withdrawal = 200
if withdrawal <= balance:
balance = balance - withdrawal # Вычесть withdrawal из balance
print(f"Withdrawal successful!")
print(f"Your new balance is: ${balance}")
print("Thank you for your transaction.")
print("Transaction complete.") # Выполняется всегдаOutput:
Withdrawal successful!
Your new balance is: $1300
Thank you for your transaction.
Transaction complete.Все четыре инструкции выполняются, потому что withdrawal <= balance равно True. Если мы изменим сумму снятия на 2000:
# bank_withdrawal_insufficient.py
balance = 1500
withdrawal = 2000
if withdrawal <= balance:
balance = balance - withdrawal
print(f"Withdrawal successful!")
print(f"Your new balance is: ${balance}")
print("Thank you for your transaction.")
print("Transaction complete.") # Выполняется всегдаOutput:
Transaction complete.Теперь ни одна инструкция с отступом не выполняется, потому что условие равно False. Баланс остаётся неизменным и равным 1500.
8.2) Использование if-else для выбора «либо-либо»
Часто нужно выбрать между двумя альтернативами: выполнить один блок кода, если условие истинно, и другой блок — если оно ложно. Оператор if-else обрабатывает такое принятие решения «либо-либо».
8.2.1) Структура if-else
Вот синтаксис:
if condition:
# Код, который нужно выполнить, если condition равно True
statement1
statement2
else:
# Код, который нужно выполнить, если condition равно False
statement3
statement4Ветка else предоставляет альтернативный путь. Ровно один из двух блоков выполнится — никогда оба, и никогда ни один.
Рассмотрим практический пример:
# age_verification.py
age = int(input("Enter your age: "))
if age >= 18:
print("You are an adult.")
print("You can vote in elections.")
else:
print("You are a minor.")
print("You cannot vote yet.")
print("Thank you for providing your age.")Если вы введёте 25:
You are an adult.
You can vote in elections.
Thank you for providing your age.Если вы введёте 15:
You are a minor.
You cannot vote yet.
Thank you for providing your age.Обратите внимание: выполняется ровно один из двух блоков — в зависимости от условия. Последний print() выполняется всегда, потому что он находится вне обоих блоков.
8.2.2) Принятие бинарных решений
if-else идеально подходит для бинарных решений, где есть ровно два возможных исхода:
# even_odd_checker.py
number = int(input("Enter a number: "))
if number % 2 == 0:
print(f"{number} is even.")
else:
print(f"{number} is odd.")# password_verification.py
stored_password = "python123"
entered_password = input("Enter password: ")
if entered_password == stored_password:
print("Access granted.")
print("Welcome to the system!")
else:
print("Access denied.")
print("Incorrect password.")8.3) Несколько вариантов с if-elif-else
Решения из реального мира часто включают больше двух вариантов. Нужно ли нам взять стандартную доставку, экспресс-доставку или доставку на следующий день? Оценка — это A, B, C, D или F? Цепочка if-elif-else обрабатывает несколько взаимно исключающих альтернатив.
8.3.1) Структура if-elif-else
Вот синтаксис:
if condition1:
# Выполнить, если condition1 равно True
block1
elif condition2:
# Выполнить, если condition1 равно False и condition2 равно True
block2
elif condition3:
# Выполнить, если condition1 и condition2 равны False, а condition3 равно True
block3
else:
# Выполнить, если все условия равны False
block4Ключевые моменты о цепочках if-elif-else:
elif— это сокращение от "else if": он добавляет дополнительные условия для проверки- Порядок важен: Python проверяет условия сверху вниз
- Первое совпадение побеждает: как только условие становится
True, выполняется соответствующий блок, а остальные пропускаются - Выполняется ровно один блок: максимум один блок в цепочке будет выполнен
elseнеобязателен: он перехватывает все случаи, не обработанные предыдущими условиями
Рассмотрим практический пример:
# grade_calculator.py
score = int(input("Enter your exam score (0-100): "))
if score >= 90:
grade = "A"
print("Excellent work!")
elif score >= 80:
grade = "B"
print("Good job!")
elif score >= 70:
grade = "C"
print("Satisfactory.")
elif score >= 60:
grade = "D"
print("You passed, but consider reviewing the material.")
else:
grade = "F"
print("Unfortunately, you did not pass.")
print(f"Your grade is: {grade}")Если вы введёте 85:
Good job!
Your grade is: BПроследим, что происходит:
- Проверка
score >= 90: False (85 не >= 90), поэтому этот блок пропускается - Проверка
score >= 80: True (85 >= 80), поэтому этот блок выполняется - Все оставшиеся блоки
elifиelseпропускаются, потому что совпадение уже найдено
Если вы введёте 55:
Unfortunately, you did not pass.
Your grade is: FВсе условия равны False, поэтому выполняется блок else.
8.3.2) Почему порядок важен в цепочках elif
Порядок условий критически важен, потому что Python прекращает проверки, как только находит условие со значением True. Рассмотрим эту неправильную систему оценивания:
# НЕПРАВИЛЬНЫЙ ПОРЯДОК — так делать не нужно!
score = 85
if score >= 60: # Это совпадёт первым!
grade = "D"
elif score >= 70:
grade = "C"
elif score >= 80:
grade = "B"
elif score >= 90:
grade = "A"
else:
grade = "F"
print(f"Your grade is: {grade}") # Output: Your grade is: DЭто даёт неправильный результат! Оценка 85 должна быть B, но получается D, потому что score >= 60 проверяется первым и равно True. Python никогда не доходит до условия score >= 80.
Всегда располагайте условия от наиболее специфичных к наименее специфичным:
# ПРАВИЛЬНЫЙ ПОРЯДОК
score = 85
if score >= 90: # Самое специфичное
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
else: # Наименее специфичное
grade = "F"
print(f"Your grade is: {grade}") # Output: Your grade is: B8.3.3) Использование elif без else
Ветка else необязательна. Иногда вы хотите обработать только определённые случаи и ничего не делать для остальных:
# weekend_checker.py
day = input("Enter a day of the week: ").lower()
if day == "saturday" or day == "sunday":
print("It's the weekend! Time to relax.")
elif day == "friday":
print("It's Friday! The weekend is almost here.")
elif day in ["monday", "tuesday", "wednesday", "thursday"]:
print("It's a weekday. Time to work or study.")
# Нет ветки else — если ничто не совпадёт, ничего не произойдёт
print("Have a great day!")Если вы введёте "holiday":
Have a great day!Ни одно условие не совпало, и ветки else нет, поэтому выполняется только последний print().
8.4) Вложенные операторы if
Иногда нужно принять решение внутри решения. Вложенные операторы if помещают одно условие внутрь другого, позволяя проверять дополнительные условия только после выполнения начального условия.
8.4.1) Понимание вложенных условий
Вложенные операторы if мощны, потому что позволяют избегать проверок условий, которые ещё не имеют смысла. Например, нет смысла спрашивать пароль, если у пользователя нет аккаунта. Вложенность позволяет структурировать логику так, чтобы она соответствовала процессам принятия решений в реальном мире, где некоторые вопросы имеют смысл только после того, как получены ответы на другие.
Вложенный оператор if — это просто оператор if (или цепочка if-elif-else) внутри другого блока if:
if outer_condition:
# Этот код выполняется, если outer_condition равно True
if inner_condition:
# Этот код выполняется, если ОБА условия равны True
inner_block
else:
# Это выполняется, если outer_condition равно True, но inner_condition равно False
inner_else_block
else:
# Это выполняется, если outer_condition равно False
outer_else_blockВнутренний оператор if вычисляется только если внешнее условие равно True. Это создаёт иерархию решений.
Вот простой пример:
# account_login.py
has_account = input("Do you have an account? (yes/no): ").lower() == "yes"
if has_account:
print("Welcome back!")
password = input("Enter your password: ")
if password == "secret123":
print("Login successful!")
print("Access granted to your dashboard.")
else:
print("Incorrect password.")
print("Access denied.")
else:
print("Please create an account first.")
print("Visit our registration page.")Если вы ответите "yes" и введёте правильный пароль:
Welcome back!
Login successful!
Access granted to your dashboard.Если вы ответите "yes", но введёте неправильный пароль:
Welcome back!
Incorrect password.
Access denied.Если вы ответите "no":
Please create an account first.
Visit our registration page.Обратите внимание: проверка пароля происходит только если у пользователя есть аккаунт. Это ключевое преимущество вложенности — вы можете избегать ненужных проверок.
8.4.2) Когда использовать вложенные операторы if
Вложенные операторы if полезны, когда:
- Решения зависят от предыдущих решений: вам нужно проверить что-то только после того, как выполнено другое условие
- Создание деревьев решений: каждый уровень сужает возможные варианты
- Проверка предварительных требований: сначала проверьте базовые требования, прежде чем проверять подробные
- Избежание ненужных проверок: пропускайте затратные операции, когда ранние условия не выполняются
Пример: право на получение кредита
# loan_eligibility.py
age = int(input("Enter your age: "))
if age >= 18:
print("Age requirement met.")
income = float(input("Enter your annual income: $"))
if income >= 30000:
print("Income requirement met.")
credit_score = int(input("Enter your credit score: "))
if credit_score >= 650:
print("Congratulations! You are eligible for a loan.")
print("Please proceed to the application form.")
else:
print("Sorry, your credit score is too low.")
print("Minimum required: 650")
else:
print("Sorry, your income is too low.")
print("Minimum required: $30,000")
else:
print("Sorry, you must be 18 or older to apply.")Это создаёт дерево решений, где каждый уровень зависит от предыдущего. Если возраст меньше 18, мы никогда не спрашиваем про доход или кредитный рейтинг.
8.4.3) Избегание чрезмерной вложенности
Хотя вложенность мощна, слишком много уровней делает код сложным для чтения и понимания. Рассмотрим этот глубоко вложенный пример:
# Слишком глубокая вложенность — сложно следить за логикой
if condition1:
if condition2:
if condition3:
if condition4:
if condition5:
print("All conditions met!")Это трудно читать и сопровождать. Вот стратегии, как уменьшить вложенность:
Стратегия 1: Объединяйте условия, когда это уместно
Мы подробно изучим оператор and в Главе 9, но пока просто знайте, что он позволяет проверять несколько условий одновременно:
# Лучше: использовать 'and' для объединения условий (Глава 9 полностью объяснит это)
# Мы изучим 'and' в Главе 9, но пока просто знайте, что он проверяет,
# что все условия истинны
if condition1 and condition2 and condition3 and condition4 and condition5:
print("All conditions met!")Стратегия 2: Используйте ранние возвраты (при работе с функциями, которые мы изучим в Главе 19):
# В функции мы можем выполнить ранний return
def check_eligibility(age, income, credit_score):
if age < 18:
return "Too young"
if income < 30000:
return "Income too low"
if credit_score < 650:
return "Credit score too low"
return "Eligible"Стратегия 3: Выравнивайте логику с помощью elif, когда это уместно:
# Вместо вложенных if, проверяющих диапазоны
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
# ... и так далее8.5) Распространённые ошибки в операторах if (отступы, двоеточия и логика)
Даже опытные программисты допускают ошибки при использовании операторов if. В этом разделе рассматриваются самые частые ошибки, с которыми сталкиваются начинающие, и способы их избежать.
8.5.1) Ошибки отступов
Python использует отступы, чтобы определить, какие инструкции к какому блоку относятся. Неправильные отступы — один из самых распространённых источников ошибок.
Проблема 1: Отсутствие отступа
# НЕПРАВИЛЬНО — IndentationError
age = 20
if age >= 18:
print("You are an adult.") # Нет отступа!Это приводит к:
File "example.py", line 4
print("You are an adult.")
^
IndentationError: expected an indented blockРешение: Всегда делайте отступ в блоке под оператором if:
# ПРАВИЛЬНО
age = 20
if age >= 18:
print("You are an adult.") # Правильный отступПроблема 2: Непоследовательные отступы
# НЕПРАВИЛЬНО — смешивание пробелов и табов или непоследовательное число пробелов
if temperature > 30:
print("It's hot!")
print("Stay hydrated!") # Лишние пробелы — непоследовательные отступыРешение: Используйте последовательные отступы (стандарт Python — 4 пробела):
# ПРАВИЛЬНО
if temperature > 30:
print("It's hot!")
print("Stay hydrated!") # Тот же уровень отступаПроблема 3: Неверные отступы во вложенности
# НЕПРАВИЛЬНО — неверный уровень отступа
if has_account:
print("Welcome!")
if password == "correct":
print("Login successful!") # Должно быть с большим отступомРешение: Каждый вложенный уровень требует дополнительного отступа:
# ПРАВИЛЬНО
if has_account:
print("Welcome!")
if password == "correct":
print("Login successful!") # Правильный отступ для вложенного блока8.5.2) Отсутствующие двоеточия
Двоеточие (:) в конце строк if, elif и else обязательно. Забыть его — очень частая ошибка:
# НЕПРАВИЛЬНО — SyntaxError: missing colon
if age >= 18
print("Adult")Это приводит к:
File "example.py", line 2
if age >= 18
^
SyntaxError: invalid syntaxРешение: Всегда ставьте двоеточие:
# ПРАВИЛЬНО
if age >= 18:
print("Adult")То же самое относится к elif и else:
# ПРАВИЛЬНО — все двоеточия на месте
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
else:
grade = "F"8.5.3) Неправильные операторы сравнения
Проблема 1: Использование присваивания (=) вместо сравнения (==)
# НЕПРАВИЛЬНО — это присваивает 18 переменной age, а не сравнивает!
age = 20
if age = 18: # SyntaxError
print("You are 18")Решение: Используйте == для сравнения:
# ПРАВИЛЬНО
age = 20
if age == 18:
print("You are 18")8.5.4) Недостижимый код из-за логических ошибок
Проблема: Условия, которые никогда не могут быть True
# НЕПРАВИЛЬНО — ветка elif никогда не выполнится
score = 85
if score >= 60:
print("You passed!")
elif score >= 80: # Это никогда не выполнится!
print("You got a B!")Если score равен 85, первое условие (score >= 60) равно True, поэтому elif даже не проверяется. Порядок неправильный.
Решение: Располагайте условия от наиболее специфичных к наименее специфичным:
# ПРАВИЛЬНО
score = 85
if score >= 80:
print("You got a B!")
elif score >= 60:
print("You passed!")8.5.5) Пустые блоки if
В Python нельзя иметь пустой блок if:
# НЕПРАВИЛЬНО — SyntaxError
if temperature > 30:
# Я добавлю код сюда позже
print("Done")Это приводит к:
File "example.py", line 3
print("Done")
^
IndentationError: expected an indented blockРешение: Используйте оператор pass как заглушку (рассматривается в следующем разделе):
# ПРАВИЛЬНО — используем pass как заглушку
if temperature > 30:
pass # TODO: Добавить код сюда позже
print("Done")8.6) Использование pass как заглушки в блоках
Иногда при написании кода вы понимаете, что вам нужен оператор if, но ещё не решили, какой код должен в него входить. Python не допускает пустых блоков кода, поэтому нужен способ создать корректный, но «ничего не делающий» блок. Здесь и помогает оператор pass.
8.6.1) Что такое pass?
Оператор pass — это нулевая операция: когда Python выполняет его, ничего не происходит. Это заглушка, которая позволяет писать синтаксически корректный код даже тогда, когда реализация ещё не готова.
if condition:
pass # Пока ничего не делатьДумайте о pass как о способе сказать Python: «Я знаю, что здесь должен быть код, но я заполню это позже». Он особенно полезен во время разработки, когда вы набрасываете структуру программы.
8.6.2) Почему pass необходим
Python требует хотя бы одну инструкцию в каждом блоке кода. Пустой блок вызывает синтаксическую ошибку:
# НЕПРАВИЛЬНО — это вызывает ошибку
if age >= 18:
# TODO: Добавить логику для взрослых здесь
print("Done")Error:
File "example.py", line 3
print("Done")
^
IndentationError: expected an indented blockИспользование pass делает код синтаксически корректным:
# ПРАВИЛЬНО — используем pass как заглушку
if age >= 18:
pass # TODO: Добавить логику для взрослых здесь
print("Done")8.6.3) Распространённые применения pass
Применение 1: Заглушка во время разработки
Когда вы намечаете структуру программы, но ещё не реализовали всё:
# user_system.py
user_type = input("Enter user type (admin/user/guest): ").lower()
if user_type == "admin":
pass # TODO: Реализовать возможности администратора
elif user_type == "user":
pass # TODO: Реализовать возможности пользователя
elif user_type == "guest":
print("Welcome, guest! Limited access granted.")
else:
print("Invalid user type.")Это позволяет запускать программу и тестировать уже реализованные части, оставляя заглушки для будущей работы.
Применение 2: Осознанно ничего не делать в одной ветке
Иногда вы действительно хотите ничего не делать в определённых случаях, но при этом обработать другие:
# positive_numbers.py
# Обрабатывать только положительные числа
number = int(input("Enter a number: "))
if number > 0:
result = number * 2
print(f"Double of {number} is {result}")
elif number == 0:
pass # Ноль допустим, но не требует действий
else:
print("Negative numbers are not allowed.")8.6.4) pass в других контекстах
Хотя мы сосредоточились на pass в операторах if, вы будете встречать его и в других контекстах по мере изучения Python:
- Функции (functions) (Глава 20): заглушка для тела функции
- Классы (classes) (Глава 31): заглушка для определения класса
- Циклы (loops) (Главы 11–12): заглушка для тела цикла
- Обработчики исключений (exception handlers) (Глава 29): преднамеренное игнорирование ошибок
Пока просто запомните, что pass — ваш инструмент для создания корректных, но пустых блоков кода, когда они вам нужны.
Собираем всё вместе
В этой главе вы узнали, как сделать ваши программы интеллектуальными и отзывчивыми с помощью условных операторов. Давайте повторим ключевые концепции:
Простые операторы if выполняют код только тогда, когда условие истинно:
if temperature > 30:
print("It's hot outside!")Операторы if-else выбирают между двумя альтернативами:
if age >= 18:
print("Adult")
else:
print("Minor")Цепочки if-elif-else обрабатывают несколько взаимно исключающих вариантов:
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"Вложенные операторы if позволяют принимать решения внутри решений:
if has_account:
if password_correct:
print("Welcome!")
else:
print("Wrong password")
else:
print("Create an account")Распространённые ошибки, которых следует избегать:
- Пропуск двоеточий после
if,elifиelse - Неправильные или непоследовательные отступы
- Использование
=вместо==для сравнения - Неправильный порядок в цепочках
elif - Пустые блоки без
pass
Оператор pass служит заглушкой для пустых блоков во время разработки.
Теперь у вас есть инструменты для написания программ, которые принимают разумные решения на основе условий. В следующей главе мы изучим операторы булевой логики (boolean logic operators) (and, or, not), которые позволяют объединять несколько условий в более сложную логику принятия решений. Это сделает ваши операторы if ещё более мощными и выразительными.