Python
Switch case в Python: match case и альтернативы
В Python долго не было отдельной конструкции switch, поэтому разработчики использовали if/elif, словарь функций или словарь значений. Начиная с Python 3.10 появился match case, но это не полная копия switch из JavaScript, Java или C#. В Python это более мощный инструмент сопоставления с образцом
Новичку важно выбрать простой вариант под задачу. Если условий мало, оставьте if/elif. Если нужно сопоставить команду с функцией, часто удобнее словарь. Если нужно разбирать структуру данных, используйте match case
Самый простой вариант через if и elif
command = input("Команда: ").strip().lower()
if command == "start":
print("Запускаем")
elif command == "stop":
print("Останавливаем")
elif command == "status":
print("Показываем статус")
else:
print("Неизвестная команда")
Такой код понятен и хорошо подходит, когда веток немного. Его минус проявляется при большом количестве команд: файл разрастается, а случайно повторить условие становится проще
Match case для команд
command = input("Команда: ").strip().lower()
match command:
case "start":
print("Запускаем")
case "stop":
print("Останавливаем")
case "status":
print("Показываем статус")
case _:
print("Неизвестная команда")
case _ — это вариант по умолчанию. Его лучше оставлять в конце, чтобы программа явно обрабатывала неизвестные значения
Несколько значений в одном case
Если разные команды должны вести к одному действию, используйте |
role = input("Роль: ").strip().lower()
match role:
case "admin" | "owner":
print("Полный доступ")
case "editor" | "manager":
print("Можно менять материалы")
case "guest":
print("Только просмотр")
case _:
print("Роль не найдена")
Это чище, чем длинное условие role == "admin" or role == "owner"
Словарь вместо switch
Для простого выбора значения словарь часто короче, чем match case
prices = {
"basic": 500,
"pro": 1200,
"team": 2500,
}
plan = input("Тариф: ").strip().lower()
price = prices.get(plan)
if price is None:
print("Тариф не найден")
else:
print(f"Цена: {price} рублей")
Такой подход хорошо подходит для справочников: тарифы, статусы, коды ошибок, роли, типы доставки
Словарь функций для действий
Если каждая команда запускает отдельное действие, можно хранить функции в словаре
def start():
print("Сервис запущен")
def stop():
print("Сервис остановлен")
def status():
print("Сервис работает")
actions = {
"start": start,
"stop": stop,
"status": status,
}
command = input("Команда: ").strip().lower()
action = actions.get(command)
if action is None:
print("Неизвестная команда")
else:
action()
Главное не вызывать функцию при создании словаря. В словаре должно быть "start": start, а не "start": start()
Match case для структуры данных
Сила match case раскрывается, когда вы разбираете списки, кортежи или словари
message = {"type": "order", "id": 42, "paid": True}
match message:
case {"type": "order", "id": order_id, "paid": True}:
print(f"Оплаченный заказ {order_id}")
case {"type": "order", "id": order_id, "paid": False}:
print(f"Заказ {order_id} ждет оплаты")
case {"type": "ping"}:
print("pong")
case _:
print("Неизвестное сообщение")
Здесь Python не просто сравнивает строку. Он проверяет форму словаря и достает значение id в переменную order_id
Когда что выбирать
if/elif— мало условий, простая логика, новичковый кодmatch case— Python 3.10+, разбор команд, статусов и структур данных- словарь значений — нужно выбрать цену, текст, настройку или код
- словарь функций — команда должна запускать отдельную функцию
Частые ошибки
Первая ошибка — пытаться использовать match case в Python 3.9 и ниже. Эта конструкция появилась в Python 3.10, поэтому проверьте версию командой python --version
Вторая ошибка — забывать case _. Без ветки по умолчанию неизвестная команда просто не выполнит ни один блок, и новичку будет сложнее понять, что произошло
Третья ошибка — писать слишком сложный match, когда обычный словарь был бы понятнее. Если вы просто выбираете значение по ключу, словарь часто лучше
Guard-условия в match case
В match case можно добавить условие через if. Это удобно, когда форма данных совпала, но нужно проверить дополнительное правило
age = int(input("Возраст: "))
match age:
case value if value < 0:
print("Возраст не может быть отрицательным")
case value if value < 18:
print("Доступ для несовершеннолетнего")
case value:
print("Полный доступ")
Такой код читается как набор правил сверху вниз. Первое подходящее правило срабатывает, остальные уже не проверяются
Разбор кортежей и списков
match case хорошо работает с командами, которые приходят как список слов
command = input("Команда: ").split()
match command:
case ["open", filename]:
print(f"Открываем {filename}")
case ["copy", source, target]:
print(f"Копируем {source} в {target}")
case ["exit"]:
print("Выход")
case _:
print("Команда не распознана")
Здесь Python проверяет не только значения, но и количество частей. Команда copy a.txt b.txt попадет в одну ветку, а open index.html — в другую
Почему в Python нет fallthrough
В классическом switch из некоторых языков есть fallthrough: выполнение может провалиться в следующий case, если не написать break. В Python match case так не работает. Сработала одна ветка — остальные пропускаются
Это снижает количество случайных ошибок. Если вам нужно выполнить общий код для нескольких вариантов, объединяйте варианты через | или вынесите общий код в функцию
Пример с enum
Для статусов удобнее использовать Enum, чтобы не разносить строки по проекту
from enum import Enum
class Status(Enum):
NEW = "new"
PAID = "paid"
CANCELLED = "cancelled"
status = Status.PAID
match status:
case Status.NEW:
print("Новый заказ")
case Status.PAID:
print("Оплачено")
case Status.CANCELLED:
print("Отменено")
Так проще ловить опечатки: Status.PAID проверяется редактором и самим Python, а строку "paidd" можно не заметить
По этой теме полезно отдельно посмотреть Составьте еженедельное расписание занятий, чтобы расширить контекст и сравнить подходы
По этой теме полезно отдельно посмотреть Аннотации типов для декораторов в Python, чтобы расширить контекст и сравнить подходы
Как переписать старый switch из другого языка
Если вы пришли из JavaScript, Java или C#, не переносите switch построчно. Сначала выпишите, что именно делает каждая ветка: возвращает значение, вызывает функцию или разбирает данные. От этого зависит Python-вариант
Если ветки возвращают значения, чаще всего нужен словарь. Если ветки выполняют действия, подойдет словарь функций или match case. Если ветки проверяют форму входных данных, используйте match case
Пример выбора текста по коду ошибки
messages = {
400: "Неверный запрос",
401: "Нужна авторизация",
404: "Не найдено",
500: "Ошибка сервера",
}
code = 404
print(messages.get(code, "Неизвестная ошибка"))
Такой код проще тестировать: словарь можно отдельно проверить, расширить и передать в функцию
Мини-тест для выбора подхода
Перед написанием кода задайте себе вопросы:
- у меня меньше пяти условий и они простые?
- я просто выбираю значение по ключу?
- мне нужно вызвать разные функции?
- я разбираю список, кортеж или словарь?
- код должен работать на Python ниже 3.10?
Если проект запускается на Python 3.9, match case использовать нельзя. Тогда выбирайте if/elif или словарь. Если версия 3.10+ и данные имеют структуру, match case может сделать код намного понятнее