Основы программирования
Условные операторы
**Загадка:** Программа должна выдать скидку 20% студентам, 15% пенсионерам, и 5% всем остальным. Как это сделать ОДНИМ блоком кода, а не тремя разными программами?
До сих пор наши программы выполнялись строка за строкой, сверху вниз. Но реальные программы должны принимать решения. Купить или не купить? Пустить или заблокировать? Показать ошибку или продолжить?
Цели урока
- Понять логику ветвления программы
- Освоить конструкции if, elif, else
- Научиться комбинировать условия
- Познакомиться с тернарным оператором
Предварительные знания
- Операторы сравнения и логические (урок 4)
- Типы данных, особенно bool (урок 3)
Любое приложение принимает тысячи решений в секунду. Авторизован? Показать контент. Нет? Показать логин. Условия - это мозг программы.
- **Авторизация**: if logged_in: show_dashboard() else: show_login()
- **Игры**: if health <= 0: game_over()
- **Платёжи**: if balance >= price: process_payment()
- **Netflix**: if age >= 18: show_adult_content()
От FORTRAN 1957 до структурного программирования: как родился if-then-else
До 1950-х код жил на условных переходах ассемблера: команда BRANCH IF NEGATIVE и метка адреса в памяти. Программа выглядела как клубок GOTO, читать её было почти невозможно. В 1957 году команда Джона Бэкуса в IBM выпустила FORTRAN: первый язык высокого уровня. Там появился арифметический IF: IF (X) 10, 20, 30 переходило на одну из трёх меток в зависимости от знака X. Это всё ещё был GOTO, но именованный. В ALGOL 58, а затем в ALGOL 60 появилась настоящая конструкция if-then-else с блоками, без меток. Эту модель скопировали почти все языки. В марте 1968 года Эдсгер Дейкстра опубликовал письмо в Communications of the ACM под названием Go To Statement Considered Harmful. Он показал, что неструктурированные переходы ломают мозг и программ, и людей, и предложил собрать всё на трёх китах: последовательность, выбор (if-then-else), повторение (while). Идея получила название структурного программирования и стала основой почти всех современных языков. Деннис Ритчи в 1972 году добавил в C тернарный оператор a ? b : c как лаконичную форму выражения if-else. Switch появился ещё в ALGOL W (1966) у Никлауса Вирта, а полноценный pattern matching пришёл из ML и Haskell в 1980-х и добрался до Python только в 3.10 (2021).
Простой if
**if** ("если") - базовая конструкция ветвления. Код внутри if выполняется только если условие истинно (True).
Синтаксис if
Базовая структура
```python age = 18 if age >= 18: print("Добро пожаловать!") # Выполнится print("Вы совершеннолетний") # Тоже выполнится print("Это выполнится всегда") # Вне блока if ``` **Важно:** - После условия - двоеточие `:` - Внутренний код - с отступом (4 пробела или Tab) - Отступ определяет, что входит в блок if
**Отступы в Python обязательны!** Они определяют структуру кода. Без отступа или с неправильным - будет ошибка IndentationError.
Условие - это выражение
Любое выражение, дающее True/False
```python password = "secret123" # Сравнение if password == "secret123": print("Доступ разрешён") # Проверка вхождения if "@" in email: print("Похоже на email") # Проверка длины if len(password) < 8: print("Пароль слишком короткий") # Логические операции if age >= 18 and has_ticket: print("Проходите") ```
Что выведет код? ```python x = 5 if x > 10: print("A") print("B") ```
if-else: два пути
**else** ("иначе") - что делать, если условие ложно. Один из двух путей выполнится всегда.
if-else в действии
Либо то, либо другое
```python age = 15 if age >= 18: print("Вход разрешён") else: print("Вход запрещён") # Выполнится это # Практический пример balance = 500 price = 300 if balance >= price: balance -= price print(f"Покупка успешна! Остаток: {balance}") else: print("Недостаточно средств") ```
Что выведет? ```python n = 7 if n % 2 == 0: print("чётное") else: print("нечётное") ```
elif: много вариантов
**elif** (else if, "иначе если") - когда вариантов больше двух. Проверяются по порядку, выполняется первый истинный.
Система оценок
Много условий
```python score = 75 if score >= 90: grade = "A" elif score >= 80: grade = "B" elif score >= 70: grade = "C" # Это выполнится (75 >= 70) elif score >= 60: grade = "D" else: grade = "F" print(f"Оценка: {grade}") # C ``` **Важно:** порядок имеет значение! Первое истинное условие срабатывает, остальные пропускаются.
Система скидок
Ответ на загадку из начала
```python is_student = False is_senior = True if is_student: discount = 20 elif is_senior: discount = 15 # Это сработает else: discount = 5 print(f"Ваша скидка: {discount}%") ```
Все elif с истинным условием выполнятся
Только ПЕРВЫЙ elif с истинным условием выполнится
elif - это "иначе если". Если предыдущее условие истинно, последующие даже не проверяются. Это оптимизация и защита от дублирования.
Что выведет? ```python x = 85 if x >= 90: print("A") elif x >= 80: print("B") elif x >= 70: print("C") ```
Вложенные условия
Условия можно вкладывать друг в друга. Но не увлекайся - глубокая вложенность делает код трудночитаемым.
Вложенные if
Условие внутри условия
```python has_ticket = True age = 15 if has_ticket: if age >= 18: print("Добро пожаловать на фильм 18+") else: print("Фильм только для взрослых") else: print("Купите билет") ```
Лучше: объединение условий
Уменьшаем вложенность
```python # Вместо вложенности: if has_ticket: if age >= 18: print("OK") # Можно написать: if has_ticket and age >= 18: print("OK") # Гораздо читаемее! ```
**Правило:** если вложенность больше 2-3 уровней - стоит рефакторинг. Используй `and`/`or`, выноси в функции, используй ранний return.
Какие два условия эквивалентны? A: ```python if x > 0: if y > 0: print("OK") ``` B: ```python if x > 0 and y > 0: print("OK") ```
Тернарный оператор
Для простых условий есть однострочная запись - **тернарный оператор**.
Синтаксис
Условие в одну строку
```python # Обычный if-else: if age >= 18: status = "взрослый" else: status = "ребёнок" # Тернарный оператор (то же самое): status = "взрослый" if age >= 18 else "ребёнок" # Ещё примеры: max_val = a if a > b else b result = "чётное" if n % 2 == 0 else "нечётное" greeting = f"Привет, {name}" if name else "Привет, гость" ```
Тернарный оператор удобен для присваивания. Но не пытайся запихнуть туда сложную логику - код станет нечитаемым.
Что будет в result после: result = "да" if 5 > 3 else "нет"?
Truthy и Falsy
В Python любое значение можно использовать как условие. Некоторые значения считаются "ложными" (falsy), остальные - "истинными" (truthy).
| Falsy (ложные) | Truthy (истинные) |
|---|---|
| False | True |
| 0, 0.0 | Любое ненулевое число |
| "" (пустая строка) | Любая непустая строка |
| [], {}, () (пустые) | Непустые коллекции |
| None | Всё остальное |
Truthy/Falsy в действии
Практические примеры
```python name = "" # Пустая строка - falsy if name: print(f"Привет, {name}") else: print("Привет, гость") # Это выполнится # То же что: # if name != "": items = [] if items: print("Есть товары") else: print("Корзина пуста") # Это выполнится # Удобный паттерн: user_name = input_name or "Аноним" # Если input_name пустой → "Аноним" ```
Что выведет? ```python if []: print("A") else: print("B") ```
Связь с другими темами
Условия открывают дверь к остальному управлению потоком:
- Циклы — while это условие плюс повторение, for оборачивает условие выхода
- Функции — Guard clauses и ранний return превращают вложенные if в линейный код
- Массивы — Фильтрация коллекций через условия: list comprehension с if
- Тестирование — Каждая ветка if это отдельная ветка тестов: покрытие веток (branch coverage)
Ключевые идеи
- **if/elif/else** - ветвление программы: код выполняется только при выполнении условия
- **elif** проверяется по порядку - первое совпавшее условие выполняется, остальные пропускаются
- **Вложенность** - условия можно вкладывать, но глубокое вложение снижает читаемость; лучше guard clause
- **Тернарный оператор** (`x if cond else y`) - для коротких однострочных условий, не для сложной логики
- **Truthy/Falsy** - в Python `0`, `None`, `[]`, `''` ложны; любая непустая структура - истинна
- **Короткое замыкание**: в `and`/`or` Python не вычисляет правую часть, если результат уже известен
Вопросы для размышления
- В функции валидации формы - 7 последовательных if-elif с проверками (email, пароль, возраст и т.д.). Первые два условия срабатывают в 90% случаев, последние - крайне редко. Как переписать логику, чтобы минимизировать количество вычислений в типичном сценарии и при этом сохранить читаемость?
Связанные уроки
- prog-04-operators — Сравнения и логические операторы строят каждое условие
- prog-07-loops — Циклы повторяют действия пока выполняется условие
- prog-08-functions — Функции оборачивают условную логику в переиспользуемые блоки
- dm-12 — Булева логика и таблицы истинности лежат под каждой ветвью
- ct-04 — Ветвление отражает взвешивание компромиссов в критическом мышлении
- alg-01-big-o