Перейти к основному содержимому

Сопоставление с образцом (match / case)

Разработчику

См. также: Управляющие конструкции · Типы данных · ООП в Python

Назначение

Начиная с Python 3.10, конструкция match / case (structural pattern matching) позволяет ветвить выполнение не только по булевому условию, но и по форме значения: константа, тип, распаковка последовательности, поля словаря, атрибуты объекта.

Это не замена if для простых проверок, а инструмент для разбора сообщений, статусов API, узлов AST, вариантов ответа дискриминированных типов.


Базовый синтаксис

def http_status(code: int) -> str:
match code:
case 200:
return "OK"
case 404:
return "Not Found"
case 500 | 502 | 503:
return "Server error"
case _:
return "Unknown"
  • case _ — ветка по умолчанию (как else);
  • case 500 | 502 — несколько литералов через | (логическое «или» внутри образца).

match вычисляет одно выражение слева и сравнивает с образцами сверху вниз до первого совпадения.


Сопоставление с типами

def describe(value):
match value:
case int() if value >= 0:
return f"неотрицательное целое {value}"
case int():
return f"отрицательное целое {value}"
case str() if not value:
return "пустая строка"
case str() as text:
return f"строка длины {len(text)}"
case _:
return "другой тип"

Класс в образце (int(), str()) проверяет тип через isinstance. Условие после if называется guard — образец подходит только если guard истинен.


Последовательности и распаковка

def head_tail(items):
match items:
case []:
return "пусто"
case [x]:
return f"один элемент: {x}"
case [first, *rest]:
return f"голова {first}, хвост из {len(rest)}"
ОбразецСмысл
[x, y]Ровно два элемента
[first, *rest]Первый + остаток в список rest
(_, _, third)Третий элемент кортежа

Работает с list, tuple и другими последовательностями при сопоставлении по структуре.


Словари и ключевые поля

def parse_event(event: dict):
match event:
case {"type": "click", "x": x, "y": y}:
return f"клик в ({x}, {y})"
case {"type": "key", "code": code}:
return f"клавиша {code}"
case {"type": str(t)}:
return f"неизвестный тип {t}"
case _:
return "не событие"

Имена ключей в образце — обязательные для совпадения; лишние ключи в словаре не мешают (в отличие от некоторых языков с «закрытыми» образцами).


Классы и dataclass

from dataclasses import dataclass

@dataclass
class Point:
x: float
y: float

def quadrant(p):
match p:
case Point(x=0, y=0):
return "начало координат"
case Point(x=x, y=y) if x >= 0 and y >= 0:
return "I четверть"
case Point(x=x, y=y):
return f"точка ({x}, {y})"

Сопоставление идёт по атрибутам, не по иерархии наследования (для иерархии классов по-прежнему удобен полиморфизм — см. ООП).


AS — привязка имени

match response:
case {"status": 200, "data": data} as ok:
process(ok["data"])
case {"status": code, "error": msg}:
log_error(code, msg)

as ok сохраняет всё совпавшее значение response, а не только извлечённые части.


match и if/elif

Критерийif / elifmatch / case
Простое сравнениеПредпочтительноИзбыточно
Много веток по одной переменнойДлинные цепочкиЧитаемее
Распаковка структурВложенные if и индексыНативно в образце
Произвольные условия между веткамиЛюбые выраженияТолько guards на case
Версия PythonЛюбая3.10+

Для кода, который должен работать на 3.9 и ниже, match недоступен — оставляйте if/elif или словари-диспетчеры.


Типичные ошибки

  1. Забыли case _ — при несовпадении возникнет MatchError (аналог необработанного случая).
  2. Изменяемые значения — образец сопоставляет текущее состояние; список может измениться после match, если на него есть другие ссылки.
  3. Порядок веток — более общий образец сверху «перехватит» частные случаи; специфичные case ставят выше общих.

Связанные материалы


См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).