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')