PEP-622


23.06.2020 — Про Python


Предлагается добавить операторы для реализации паттерна сопоставления с образцом. Необходимо это для того, чтобы упростить взаимодействие с разнородными данными и не городить if ... elif ... вместе с вечной проверкой на isinstance(). Наши методы/функции очень часто принимают в свои аргументы разные типы данных и данный math нам упростит реализации.

Вот как это будет выглядеть:

match some_expression:
    case pattern_1:
        ...
    case pattern_2:
        ...

Суть в том, что мы проходимся по нашему списку паттернов, если где-то ему соответствуем - заходим внутрь и выполняем перечень операторов. На другие паттерны мы больше не смотрим! Если подходящего паттерна нет, то ничего не происходит и выполняется код ниже самого match.

Никаких поведений по умолчанию нет, но их можно задать самостоятельно (пустой name pattern "").

Предлагаются следующие типы паттернов: name, literal, constant, group, sequence, mapping, class. Отдельным паттерном является guards.

Большинство понятно из названий. Тут вам и case 0: и case name, где name аттрибут объекта и выходит как замена getattr() с пробрасыванием значения внутрь

match greeting:
    case name:
        print(f"Hi {name}!")

И по константам с Enum с всякими логическими "или" через | (да-да, не через or). Ну и классы конечно же, который имеют новый magic method, стандартная реализация которого следующая:

def __match__(cls, instance):
        if isinstance(instance, cls):
            return instance

Стоит отметить отдельный от всех паттерн Guard. Он позволяет писать условные выражения внутри case, например:

match input:
    case [x, y] if x > MAX_INT and y > MAX_INT:
        print("Got a pair of large numbers")

Больше подробностей по другим паттернам и примерам вы найдете в самом PEP'e, а теперь несколько интересных фактов:

  1. Данный PEP полностью обратно совместим так как новые ключевые слова (match, case) остаются как soft keywords, а это значит, что их можно продолжать использовать как имена переменных!
  2. Литералы с плавающей точкой не запретили, несмотря на их неточность.
  3. Ренджи аля 1..6 не добавят, потому что возникает куча вопросов. Один из которых про рендж 'a'..'z', но в Python нет символьного типа, только string, а следовательно это невозможно.
  4. Контролировать как-то поведение прохождения по паттернам с помощью continue и break не будет доступно. Строго только та логика, что описана в самом начале данного поста. Потому что, например, если match находится внутри цикла, то понимаете что будет...
  5. Несмотря на наличие оператора | (or) оператор & (and) отсутствует. Предлагается использовать Guards.
  6. Использовать ! как not нельзя.
  7. Тайпхинтинг (аннотации типов) не будет доступен вместе с этими паттернами из-за огромного количества возникающих проблем ✨

Недавние посты


© marshal.by 2020

Исходный код

Сайт работает на Gatsby + prismic и опубликован на GitHub.