match реализует не сравнение, а т.н. Сопоставление с образцом - очень распространенный прием в функциональном программировании.
Значение в match сопоставляется с одним или несколькими образцами, состоящими из литералов, имен классов и переменных. Тело первого case с совпадающим образцом выполняется, остальные игнорируются. При этом переменным из образца присваиваются значения, которым они соответствуют.
lst = [1, 2, 3, 4, 5, 6]
match lst:
case [x, _, y, _, *rest]:
print(x, y, rest) # 1 3 [5, 6]
Переменные x
, y
, rest
создаются в этом месте. Сравнения с ними не производится.
В некотором смысле эта конструкция похожа на обычное множественное присваивание
[x, _, y, _, *rest] = lst
print(x, y, rest) # 1 3 [5, 6]
За некоторыми исключениями:
- В случае несоответствия выражения образцу не произойдет ошибки
match [1]:
case x, y, z: # эта ветка проигнорируется
pass
x, y, z = [1] # ошибка
- Паттерны вроде
(x,y,z)
, [x,y,z]
, x,y,z
(это синонимы), как в примере выше, нельзя сопоставлять произвольным итерируемым объектам, только последовательностям (реализующим Sequence), кроме строк (и bytes).
match 'test':
case x, y, *z: # здесь не будет совпадения
print(x, y, z)
match map(int, '1234'):
case x, y, *z: # здесь тоже
print(x, y, z)
x, y, *z = 'test'
print(x, y, z) # t e ['s', 't']
x, y, *z = map(int, '1234')
print(x, y, z) # 1 2 [3, 4]
_
является частью синтаксиса, а не именем переменной, и эта часть выражения по настоящему игнорируется, ни чему не присваивается, и время на ее копирование не тратится.
match range(1000000):
case x, *_, y: # здесь время потратится только на извлечение двух элементов
print(x, y) # 0 999999
# попытка вывести _ приведет к ошибке отсутствия соответствующей переменной
x, *_, y = range(1000000) # здесь - также на копирование последовательности в список `_`
print(_) # [1..99998]
Т.к. просто имени переменной удачно сопоставляется любое выражение, в вашем случае
match a:
case b:
# здесь b при сваеивается значение a
это то же самое, что
b = a
Но если вам действительно нужно сравнение
a = 2
b = 2
match a:
case 1: print("1!")
case x if x == b: print("2!") #<-- так можно.
case 3: print("3!")
Конечно, этим возможности сопоставления не ограничиваются. Особенно удобно использовать их с датаклассами, или другими классами реализующими соответствующий функционал
from dataclasses import dataclass
@dataclass
class Data:
x: bool
y: str
for rec in [Data(True, 'a'), Data(True, 'B'), Data(False, 'b')]:
match rec:
case Data(True, y) if y.islower():
print(y)
case _:
print(rec, "не совпадает")
a
Data(x=True, y='B') не совпадает
Data(x=False, y='b') не совпадает
case b:
определяет новую переменную, равную значению выражения изmatch
. Так сделано.