Оператор switch/case
- это оператор, который оценивает точность или сходство переданного значения. Почти во всех языках (таких как Java и .NET C# и т.д.), в синтаксисе, присутствует оператор switch/case
.
В версии Python 3.10 Гвидо ван Россум анонсировал конструкцию pattern matching (сопоставление с образцом). Саму концепцию сложно назвать новой, она уже реализована во многих языках как switch/case
. Синтаксически конструкция pattern matching по сути аналогична тому, как это представлено в ряде других языков.
Начиная с Python 3.10 эта конструкция представлена сочетанием операторов match/case
:
match some_expression: case pattern_1: ... case pattern_2: ...
switch/case
до Python 3.10Между тем, до версии Python 3.10 прекрасно обходился без конструкции match/case
. Случай с оператором match
очень похож на оператор if/elif/else
. По большому счету это то же самое, что делает оператор if/elif/else
.
fruit = "banana" if fruit == "apple": print("The fruit is apple") elif fruit == "banana": print("The fruit is banana") elif fruit in ("blueberries", "raspberries", "blue currant", "currant"): print("The fruit is berries") else: print("The fruit is unknown")
Приведенный выше код просто читать и понимать. Но это все еще не оператор switch/case
. switch
оценивает точность, но также и сходство слова. В python есть объект, который действует как селектор.
Селектор оценивает выражение, принимает его значение и проверяет точность шаблона, в противном случае он возвращает значение по умолчанию. В Python объект словаря - это своего рода селектор:
Объект сопоставления в Python отображает хешируемые значения на произвольные объекты. Сопоставления - это изменяемые объекты. В настоящее время существует только один стандартный тип сопоставления - dict
.
Основываясь на хэш-индексах, он намного быстрее извлекает значения. Попробуем создать селектор.
fruits = { "apple": "The fruit is apple", "banana": "The fruit is banana", "blueberries": "The fruit is berries", "raspberries": "The fruit is berries", "blue currant": "The fruit is berries", "currant": "The fruit is berries" } >>> myfruit = "banana" >>> print(fruits.get(myfruit, "The fruit is unknown")) # The fruit is banana
Таким образом switch
-селектор получился красивым и "питоническим". Но все равно оценивается только точность слова, а сходство слова - нет.
Как можно улучшить код, представленный выше? Создадим функцию, которая будет действовать как селектор (оценивать точность и сходство переданного в нее слова). Что бы добиться такого поведения нужна функция, которая оценивает сходство ключей словаря. Такая функция есть в Python и называется filter()
.
def fruit_selector(fruit): fruits = { "apple": "The fruit is apple", "banana": "The fruit is banana", "blueberries": "The fruit is berries", "raspberries": "The fruit is berries", "blue currant": "The fruit is berries", "currant": "The fruit is berries", "default": "The fruit is unknown" } return dict(filter(lambda key: fruit in key[0], fruits.items())) >>> fruit_selector('banana') >>> fruit_selector('anana')
В python методы классов и функций являются объектами типа Callable. Как объекты, в них может храниться информация. Превратим fruit_selector()
в switch
с дополнительным значением: кеш последнего выбранного фрукта. В Python все является объектом и, следовательно, может рассматриваться как таковое. Если бы было необходимо еще больше абстрагировать селектор, то он фактически стал похож на switch
, вот и все:
def switch(match, dictionary, default="no match"): for key in dictionary.keys(): if match in key: return dictionary.get(key) return default fruits = { "apple": "The fruit is apple", "banana": "The fruit is banana", "blueberries": "The fruit is berries", "raspberries": "The fruit is berries", "blue currant": "The fruit is berries", "currant": "The fruit is berries" } >>> switch('banana', fruits) # 'The fruit is banana' >>> switch('anana', fruits) # 'The fruit is banana' >>> switch(switch.last_match, fruits, default="The fruit is unknown") # 'The fruit is banana'
Так как функции в Python являются объектами, то можно заменить значения ключей словаря функциями и возвращать их, если ключи совпадают. Очень простой пример.
def switch(match, dictionary, default="no match"): for key in dictionary.keys(): if match in key: return dictionary.get(key) return default calc = { "plus": lambda x, y: x + y, "minus": lambda x, y: x - y } >>> plus = switch('plus', calc, default="unintended function") >>> minus = switch('minus', calc, default="unintended function") >>> plus(6, 4) # 10 >>> minus(6, 4) # 2