Python 3.10引入了新的語法——結構模式匹配(Structural Pattern Matching)。即match-case。

字面量(Literal)模式

編輯

使用Python自帶的基本數據結構,如字符串、數字、布爾值和None:

match number:
    case 0:
        print('zero')
    case 1:
        print('one')
    case 2:
        print('two')
    case _:  # 使用单下划线_匹配任何结果,但是不绑定(不赋值到某个或者某些变量上)
        print('Other cases')

捕捉(Capture)模式

編輯

可以匹配單個表達式的賦值目標。

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

如果greeting為None會拋NameError或者UnboundLocalError錯誤,因為name在之前沒有定義過。

序列(Sequence)模式

編輯

可以在match里使用列表或者元組格式的結果,還可以按照PEP 3132 – Extended Iterable Unpacking裡面使用first, *rest = seq模式來解包。

def sequence2(collection):
    match collection:
        case 1, [x, *others]: # 匹配 1 和一个列表组成的对象,如 [1, [2, 3]]
            print(f"Got 1 and a nested sequence: {x=}, {others=}")
        case 1, x:
            print(f"Got 1 and {x}")
        case x, y, z:
            print(f"{x=}, {y=}, {z=}")

通配符模式

編輯

使用通配符需求注意邏輯順序,把範圍小的放在前面,範圍大的放在後面

def wildcard(data):
    match data:
        case [_, _]:
            print('Some pair')
        case ["a", *_, "z"]:
            print('matches any sequence of length two or more that starts with "a" and ends with "z".')
        case (_, _, *_):
            print('matches any sequence of length two or more.')
        case [*_]:
            print('matches a sequence of any length.')
ù

常量值(constant value)模式

編輯

這種模式主要匹配常量或者enum模塊的枚舉值:

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

class NewColor:
    YELLOW = 4

def constant_value(color):
    match color:
        case Color.RED:
            print('Red')
        case NewColor.YELLOW:
            print('Yellow')
        case new_color: #实际上绑定到变量new_color
            print(new_color)

映射(Mapping)模式

編輯

就是case後支持使用字典做匹配:

def mapping(config):
    match config:
        case {'sub': sub_config, **rest}:
            print(f'Sub: {sub_config}')
            print(f'OTHERS: {rest}')
        case {'route': route}:
            print(f'ROUTE: {route}')

類(Class)模式

編輯

case後支持任何對象做匹配。對於匹配來說,位置需要確定,所以需要使用位置參數來標識:

def class_pattern(obj):
    match obj:
        case Point(x=1, y=2):
            print(f'match')

組合(OR)模式

編輯

可以使用|將多個字面量組合起來表示或的關係,|可以在一個case條件內存在多個,表示多個或關係:

def or_pattern(obj):
    match obj:
        case 0 | 1 | 2: # 0,1,2三个数字匹配
            print('small number')
        case list() | set():  # 列表或者集合匹配
            print('list or set')
        case str() | bytes():  # 字符串或者bytes符合
            print('str or bytes')
        case Point(x, y) | Point2(x, y):  # 借用之前的2个类,其中之一符合即可
            print(f'{x=},{y=}')
        case [x] | x:  # 列表且只有一个元素或者单个值符合
            print(f'{x=}')

AS模式

編輯

AS模式在早期其實是海象(Walrus)模式,後來討論後發現使用as關鍵字可以讓這個語法更有優勢:

def as_pattern(obj):
    match obj:
        case str() as s:
            print(f'Got str: {s=}')
        case [0, int() as i]:
            print(f'Got int: {i=}')
        case [tuple() as tu]:
            print(f'Got tuple: {tu=}')
        case list() | set() | dict() as iterable:
            print(f'Got iterable: {iterable=}')

模式添加if條件(guard)

編輯
def go(obj):
    match obj:
        case ['go', direction] if direction in ['east', 'north']:
            print('Right way')
        case direction if direction == 'west':
            print('Wrong way')
        case ['go', _] | _:
            print('Other way')