[Перевод] Матчинг шаблона в Python 3.10
В Python 3.10 имплементирован своего рода оператор switch
— что-то вроде него. Оператор switch
в других языках, таких как C или Java, выполняет простой матчинг значения переменной и исполняет код в зависимости от этой величины.
Он может использоваться просто, как обычный оператор switch
, но способен на гораздо большее.
Возможно, этого было бы достаточно для языка C, но ведь речь о Python, а в Python 3.10 реализована гораздо более мощная и гибкая конструкция, называемая структурным сопоставлением шаблона. Она может использоваться как простой оператор switch
, но способна на гораздо большее.
Давайте рассмотрим несложный пример с оператором switch
. Ниже приведен сниппет, который осуществляет выбор одного значения. Мы проверим его, запустив в цикле со значениями 1,2,3 и 4.
for thing in [1,2,3,4]:
match thing:
case 1:
print("thing is 1")
case 2:
print("thing is 2")
case 3:
print("thing is 3")
case _:
print("thing is not 1, 2 or 3")
Первое, что бросается в глаза, — это аккуратность синтаксиса. Он начинается с ключевого слова match
, за которым следует имя переменной. Затем идет список кейсов, начинающийся с case
и сопровождающийся значением, которое сопоставляется. Обратите внимание на использование двоеточий и отступов.
Это не отличается от оператора switch/case
в других языках, но в отличие, например, от языка C, после исполнения кода для конкретного кейса проверка переходит к завершению оператора match
.
Если совпадения нет, то происходит выполнение кода в случае по умолчанию, обозначенном символом -
.
И вот результат.
thing is 1
thing is 2
thing is 3
thing is not 1, 2 or 3
В этом нет ничего удивительного.
Оператор switch
— это простой кейс матчинга шаблона, но Python идет немного дальше. Взгляните на этот код:
for thing in [[1,2],[9,10],[1,2,3],[1],[0,0,0,0,0]]:
match thing:
case [x]:
print(f"single value: {x}")
case [x,y]:
print(f"two values: {x} and {y}")
case [x,y,z]:
print(f"three values: {x}, {y} and {z}")
case _:
print("too many values")
Это снова оператор match
в цикле, но на этот раз в качестве перечня значений, которые цикл будет итерировать, выступают сами списки — сначала [1,2] затем [9,10] и так далее.
Операторы case
пытаются выполнить матчинг этих списков. Первый case
соответствует списку с одним элементом, второй — списку с двумя элементами, третий — списку с тремя элементами. Последний case используется по умолчанию.
Но он делает больше, чем это. Он также выполняет биндинг значений, которые сопоставляются с идентификаторами в операторе case. Так, например, первый список — это [1,2]
, и он соответствует второму случаю [x,y]
. Таким образом, в выполняемом коде идентификаторы x и y принимают значения 1 и 2, соответственно. Совсем неплохо, правда?
Итак, результат таков:
two values: 1 and 2
two values: 9 and 10
three values: 1, 2 and 3
single value: 1
too many values
Из нашей первой несложной программы мы знаем, что можно выполнять матчинг значений, а из приведенной выше — матчинг других, более общих шаблонов. Итак, можем ли мы делать матчинг шаблонов, включающих значения? Конечно!
for thing in [[1,2],[9,10],[3,4],[1,2,3],[1],[0,0,0,0,0]]:
match thing:
case [x]:
print(f"single value: {x}")
case [1,y]:
print(f"two values: 1 and {y}")
case [x,10]:
print(f"two values: {x} and 10")
case [x,y]:
print(f"two values: {x} and {y}")
case [x,y,z]:
print(f"three values: {x}, {y} and {z}")
case _:
print("too many values")
Например, во втором кейсе мы осуществляем матчинг списка, состоящего из двух элементов, первый из которых имеет значение 1.
Вот результат:
two values: 1 and 2
two values: 9 and 10
two values: 3 and 4
three values: 1, 2 and 3
single value: 1
too many values
Но это еще не все.
Вот программа, которая будет выполнять матчинг списка с любым количеством элементов.
for thing in [[1,2,3,4],['a','b','c'],"this won't be matched"]:
match thing:
case [*y]:
for i in y:
print(i)
case _:
print("unknown")
В первом case
индентификатор отмечен звездочкой, и это означает, что к нему можно привязать весь список, который, как мы видим, можно итерировать с помощью цикла.
1
2
3
4
a
b
c
unknown
Это еще не все, но, надеюсь, данная статья дала вам представление о структурном сопоставлении шаблона в Python 3.10.
Более расширенно о дополнительном способе матчинга шаблона я писал здесь.
На сайте Python.org есть полное описание структурного сопоставления шаблона, включая учебное руководство, в PEP 636. Учебник довольно хороший, и я советую вам его прочитать.
В Python 3.10 довольно много новых разработок, помимо структурного матчинга шаблона. О них рассказывается в нескольких статьях, например, см. Джеймс Бриггс Новые возможности в Python 3.10.
Однако имейте в виду, что 3.10 еще только бета-версия, и хотя примеры, которые я показал выше, работают отлично, вам не следует использовать Python 3.10 со всей серьезностью до его официального релиза.
Приглашаем всех заинтересованных на открытое занятие »Знакомство с веб разработкой на Flask». На нем познакомимся с основами веб разработки на Flask, а также научимся создавать и рендерить шаблоны страниц. Попробуем создать Flask приложение, затем создать роуты и в конце обработать различные HTTP методы на Flask. Регистрирация — по ссылке.