Добавить в корзинуПозвонить
Найти в Дзене
Удалёнка

Python. Кортежи в pattern matching

В качестве шаблонов в pathern matching в Python могут выступать кортежи. Например: def print_data(user): match user: case ("Tom", 37): print("default user") case ("Tom", age): print(f"Age: {age}") case (name, 22): print(f"Name: {name}") case (name, age): print(f"Name: {name}  Age: {age}") print_data(("Tom", 37))     # default user print_data(("Tom", 28))     # Age: 28 print_data(("Sam", 22))     # Name: Sam print_data(("Bob", 41))     # Name: Bob  Age: 41 print_data(("Tom", 33, "Google"))    # не соответствует ни одному из шаблонов В данном случае функция принимает параметр user, который, как предполагается, представляет кортеж из двух элементов. И конструкция match сравнивает этот кортеж с рядом шаблонов. Первый шаблон предполагает, что кортеж user точно соответствует набору значений: case ("Tom", 37): print("default user") То есть, если первый элемент кортежа равен "Tom", а второй - 37, то на консоль выводится строка "default user" Второй шаблон соответствует любому двухэлементному к
Оглавление

В качестве шаблонов в pathern matching в Python могут выступать кортежи. Например:

def print_data(user):

match user:

case ("Tom", 37):

print("default user")

case ("Tom", age):

print(f"Age: {age}")

case (name, 22):

print(f"Name: {name}")

case (name, age):

print(f"Name: {name}  Age: {age}")

print_data(("Tom", 37))     # default user

print_data(("Tom", 28))     # Age: 28

print_data(("Sam", 22))     # Name: Sam

print_data(("Bob", 41))     # Name: Bob  Age: 41

print_data(("Tom", 33, "Google"))    # не соответствует ни одному из шаблонов

В данном случае функция принимает параметр user, который, как предполагается, представляет кортеж из двух элементов. И конструкция match сравнивает этот кортеж с рядом шаблонов. Первый шаблон предполагает, что кортеж user точно соответствует набору значений:

case ("Tom", 37):

print("default user")

То есть, если первый элемент кортежа равен "Tom", а второй - 37, то на консоль выводится строка "default user"

Второй шаблон соответствует любому двухэлементному кортежу, первый элемент которого равен строке "Tom":

case ("Tom", age):

print(f"Age: {age}")

Для второго элемента определяется переменная age. В итоге, если первый элемент кортежа равен строке "Tom", а второй не равен 37, то такой кортеж будет соответствовать второму шаблону. Причем второй элемент будет передаваться переменной age.

Третий шаблон во многом аналогичен, только теперь строго определен второй элемент кортежа - он должен быть равен 22, а первый попадает в переменную name:

case (name, 22):

print(f"Name: {name}")

Если двухэлементный кортеж не соответствует первому, второму и третьему шаблонам, то он будет соответствовать четвертому шаблону, в которому нам не важные конкретные значения - для них определены переменные name и age:

case (name, age):

print(f"Name: {name}  Age: {age}")

Альтернативные значения

Если необходимо, чтобы элемент кортежа соответствовал набору значений, то эти значения можно перечислить через вертикальную черту:

def print_data(user):

match user:

case ("Tom" | "Tomas" | "Tommy", 37):

print("default user")

case ("Tom", age):

print(f"Age: {age}")

case (name, 22):

print(f"Name: {name}")

case (name, age):

print(f"Name: {name}  Age: {age}")

print_data(("Tom", 37))     # default user

print_data(("Tomas", 37))   # default user

print_data(("Tom", 28))     # Age: 28

print_data(("Sam", 37))     # Name: Sam  Age: 37

В данном случае первый шаблон соответствует двухэлементному кортежу, где первый элемент равен или "Tom", или "Tomas", или "Tommy".

Также можно задать альтернативные значения для отдельных элементов, но и альтернативные кортежи:

def print_data(user):

match user:

case ("Tom", 37) | ("Sam", 22):

print("default user")

case (name, age):

print(f"Name: {name}  Age: {age}")

print_data(("Tom", 37))     # default user

print_data(("Sam", 22))     # default user

print_data(("Mike", 28))    # Name: Mike  Age: 28

В данном случае первый шаблон будет соответствовать двум кортежам: ("Tom", 37) и ("Sam", 22)

Пропуск элементов

Если нам не важен какой-то элемент кортежа, то в шаблоне вместо конкретного значния или переменной можно указать шаблон _:

def print_data(user):

match user:

case ("Tom", 37):

print("default user")

case (name, _):     # второй элемент не важен

print(f"Name: {name}")

print_data(("Tom", 37))     # default user

print_data(("Sam", 25))     # Name: Sam

print_data(("Bob", 41))     # Name: Bob

Можно использовать прочерки для всех элементов кортежа, в этом случае значения всех этих элементов будут не важны:

def print_data(user):

match user:

case ("Tom", 37):

print("default user")

case ("Sam", _):

print("Name: Sam")

case (_, _):

print("Undefined user")

print_data(("Tom", 37))     # default user

print_data(("Sam", 25))     # Name: Sam

print_data(("Bob", 41))     # Undefined user

В причем в последнем случае шаблон (_, _) по прежнему соответствует только двухэлементному кортежу

В примере выше применяемые шаблоны соответствовали только двухэлементному кортежу. Однако также можно использовать одновременно шаблоны кортежей с разным количеством элементов:

def print_data(user):

match user:

case (name, age):

print(f"Name: {name}  Age: {age}")

case (name, age, company):

print(f"Name: {name}  Age: {age}  Company: {company}")

case (name, age, company, lang):

print(f"Name: {name}  Age: {age}  Company: {company} Language: {lang}")

print_data(("Tom", 37))                     # Name: Tom  Age: 37

print_data(("Sam", 22, "Microsoft"))        # Name: Sam  Age: 22  Company: Microsoft

print_data(("Bob", 41, "Google", "english"))

# Name: Bob  Age: 41  Company: Google Language: english

Кортеж с неопределенным количеством элементов

Если необходимо сравнивать выражение с кортежем неопределенной длины, то можно определять все остальные значения кортежа с помощью символа * (звездочки):

def print_data(user):

match user:

case ("Tom", 37, *rest):

print(f"Rest: {rest}")

case (name, age, *rest):

print(f"{name} ({age}): {rest}")

print_data(("Tom", 37))               # Rest: []

print_data(("Tom", 37, "Google"))     # Rest: ["Google"]

print_data(("Bob", 41, "Microsoft", "english"))     # Bob (41): ["Microsoft", "english"]

В примере выше применяется параметр *rest, который соответствует всем остальным элементам. То есть в примере выше шаблоны ("Tom", 37, *rest) и (name, age, *rest) соответствуют любому кортежу с двумя элементами и больше. Все элементы начиная с третьего будут помещаться в параметр rest, который представляет массив значений.

Если нам этот параметр (rest) не важен, но мы по прежнему хотим, чтобы шаблон соответствовал кортежу с неопределенным количеством элементов, мы можем использовать подшаблон *_:

def print_data(user):

match user:

case ("Tom", 37, *_):

print("Default user")

case (name, age, *_):

print(f"{name} ({age})")

print_data(("Tom", 37))               # Default user

print_data(("Tom", 37, "Google"))     # Default user

print_data(("Bob", 41, "Microsoft", "english"))     # Bob (41)