Новый оператор match-case в Python

В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

ПрограммыКодPython

От версии к версии Python дарит нам разные новые возможности сделать наш код более понятным, более подходящим под задачи. На этот раз - появится оператор match-case. В некотором смысле он похож на паттерн-матчинг оператор из функциональных языков.

В общем случае его можно описать как расширенный switch-case, однако, куда более крутой:

    match command.split():
        case ["quit"]: ... # Code omitted for brevity
        case ["go", direction]: ...
        case ["drop", *objects]: ...
        ... # Other cases
        case _:
            print(f"Sorry, I couldn't understand {command!r}")

В match мы указываем значение для сопоставления, в case - значения, которые могут подходить. При чём, это могут быть композитные значения.

В предложенном примере после метода split значением будет массив - введённая команда, разделённая на части по пробелу. Тогда благодаря match-case мы можем обработать разные ситуации: когда одно слово "quit", когда несколько слов а ля "go" и какое-то "направление" и т.д.

Иными словами, от входящего значения мы можем описать разные сценарии. При предыдущих "if-else" это было бы не так просто, не так очевидно.

Более того! Мы можем использовать сопоставление с образцом - объектом. То есть (если вы такой ленивец-негодяй-панк, что не следите за типами в апи) можно обрабатывать входящие данные без isinstance:

    match event.get():
        case Click(position=(x, y)):
            handle_click_at(x, y)
        case KeyPress(key_name="Q") | Quit():
            game.quit()
        case KeyPress(key_name="up arrow"):
            game.go_north()
        ...
        case KeyPress():
            pass # Ignore other keystrokes
        case other_event:
            raise ValueError(f"Unrecognized event: {other_event}")

Разные типы - разные обработчики! Равно как и разные значения типов...

Можно также использовать позиционные атрибуты (это по мне - вообще рвань!):

    from dataclasses import dataclass

    @dataclass
    class Click:
        position: tuple
        button: Button


    match event.get():
        case Click((x, y)):
            handle_click_at(x, y)

Или без dataclass через магический аттрибут __match_args__ = ["position", "button"] - ещё одна фигня, на которой будут отыгрываться "злые" рекрутеры.

Вам мало? Вот ещё это работает с "or":

    case 401 | 403 | 404:
        return "Not allowed"

или диктами:

    case {"text": str(message), "color": str(c)}:
        ui.set_text_color(c)
        ui.display(message)

"Ахаха, Девид Блейн, прекрати!" - держите ещё guard-условия:

    case Point(x, y) if x == y:
        print(f"Y=X at {x}")

В общем, завезли много нового, пусть и в одном операторе.

Фото Нет слов, одни... однострочники

Нет слов, одни... однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Фото Добавляем постраничную пагинацию на Django сайт

Добавляем постраничную пагинацию на Django сайт

На сайтах часто встречаются многостраничные объекты: список товаров, список заметок и т.д. Поэтому важно уметь добавить навигацию по страницам на Django-проекте.