Python Match/Case高级用法之匹配序列

python标准库用c语言实现了丰富的序列,主要分成两列:
容器序列:可存放不同类型的项,其中包括嵌套容器。⽰例:list、tuple和collections.deque。
扁平序列:可存放⼀种简单类型的项。⽰例:str、bytes 和array.array。
容器序列存放的是所包含对象的引⽤,对象可以是任何类型。扁平序列在⾃⼰的内存空间中存储所含内容的值,⽽不是各⾃不同的Python对象。

在3.10版本一个引人注目的功能就是match/case语句匹配模式的出现。我们大多数使用match匹配的场景比较简单,用于匹配序列的场景比较少。直接开始,下面使用match/case处理序列的一个第一个示例:

def match_commend(self, commands):
    match commands:  # match后面跟的是匹配对象
         # 这个模式匹配包含三个匹配项,第一个必须是字符串"LIGHT",第二三项任意,依次绑定到变量off, times上
        case ["LIGHT", off, times]: 
            self.open_light(off, times)
        case ["Air", low]:  # 这个有两项,匹配第一个为"Air"的字符串序列,后面的绑定带low变量上面
            self.open_light(low)
        case ["LED", ident, red, green, blue]:
            self.leds[ident].set_color(ident, red, green, blue)
        case _:  # 这是默认的case ⼦句,前⾯所有模式都不匹配时执⾏
            raise InvalidCommand(commands)

从表面上看,python的match/case和c语言的switch/case很相似,但是这只是表象,与switch相比,match支持析构,这是一种高级的拆包形式,下面来使用match/case来析构嵌套元组:

city_sight = [
    ("北京", "北京市", "故宫", (116.40, 39.9)),
    ("长沙", "湖南省", "橘子洲", (112.93, 28.23)),
    ("武汉", "湖北省", "故宫", (114.30, 30.60)),
    ("成都", "四川省", "大熊猫", (104.07, 30.67)),
]


def match_sight():
    for sight in city_sight:
        match sight:
            # 这个case ⼦句由两部分组成:⼀部分是模式,另⼀部分是使⽤if关键字指定的卫语句(可选的),仅当匹配模式时才运⾏,如果为真才进行后续print
            # _ 符号在模式中有特殊意义:匹配相应位置上的任何⼀项,但不绑定匹配项的值。另外,_ 是唯⼀可在模式中多次出现的变量。
            case [city, _, _, (lat, lon)] if lat > 112:
                print(f'{city:5} | {lat:9.4f} | {lon:9.4f}')

一般来说,匹配对象需要满足以下条件方能匹配序列模式
1、匹配对象是序列
2、匹配对象和模式的项数相等
3、对应的项相互匹配,包括嵌套的项

序列模式可以写成元祖或者列表,或者任意形式的嵌套元祖或者列表,使用那种句法都没区别,因为在序列模式中,圆括号和方括号的作用是一样的,上述案例中模式使用列表形式,里面嵌套元祖形式是为了避免重复使用列表或者元祖

序列模式可以匹配collections.abc.Sequence 的多数实际⼦类或虚拟⼦类的实例,但 str、bytes 和bytearray 除外,因为在match/case 上下⽂中,str、bytes 和bytearray实例不作为序列处理。match 把这些类型视为“原⼦”值,就像整数987 整体被视为⼀个值,⽽不是数字序列。

标准库中的以下类型与序列模式兼容。

listmemoryview  array.array
tuple  range        collections.deque

与拆包不同,模式不析构序列以外的可迭代对象(如生成器)
模式中的任一部分均可使用as关键字绑定到变量上,如:

case [city, _, _, (lat, lon) as lat_lon]:
        print(lat_lon)  # 输出(116.4, 39.9)

也可以添加类型信息可能让模式更加具体,例如下面模式,其中city必须是str类型,lat和lon必须是float类型:

case [str(city), _, _, (float(lat), float(lon))]:

此外,如果想要匹配任何以字符串开头、以嵌套两个浮点数的序列结尾的序列,则可以使⽤如下模式

case [str(city), *_, (float(lat), float(lon))]:

*_ 匹配任意数量的项,⽽且不绑定变量。如果把*_ 换成*extra,匹配的零项或多项将作为列表绑定到extra 变量上。

对拆包、析构和模式匹配到此结束。其他模式类型有机会后续再补充哈

 

 

### Python 中 `match` 和 `case` 的语法及示例 自 Python 3.10 起引入的结构化模式匹配功能允许开发者通过 `match` 和 `case` 关键字实现更强大的分支逻辑。这种特性类似于其他编程语言中的 switch-case 结构,但提供了更为灵活和强大的模式匹配能力。 #### 基本语法 `match` 语句接受一个表达式并将其与一系列 `case` 子句逐一比较。如果某个子句匹配成功,则执行该子句内的代码块。以下是基本形式: ```python match subject: case pattern_1: action_1 case pattern_2: action_2 ... case _: default_action ``` 其中: - **subject**: 是要被匹配的对象。 - **pattern**: 定义了如何匹配对象以及提取其部分数据的方式。 - **action**: 当对应的模式匹配成功时所执行的操作。 - `_`: 表示通配符,默认情况下会匹配任何未处理的情况。 #### 示例:简单数值匹配 下面是一个简单的例子,展示如何基于整数输入返回不同的字符串描述。 ```python def number_to_text(num): match num: case 1: return "One" case 2: return "Two" case _: return f"Unknown number {num}" ``` #### 序列匹配 当需要匹配列表或其他可迭代类型的特定结构时,可以利用序列模式[^1]。例如,对于长度固定的元组或者具有某些已知前缀的列表都可以定义相应的匹配条件。 ```python from array import array data = (1, 'a', True) match data: case int(x), str(y), bool(z): print(f"Mixed tuple with values: ({x}, '{y}', {z})") case _: print("Not a mixed tuple of an integer, string and boolean.") arr = array('i', [1, 2, 3]) match arr: case memoryview(): print("It's a memory view object!") case array() as ar: if len(ar) == 3: print("Array contains exactly three elements:", *ar) case _: print("Something else entirely...") ``` 上述代码片段展示了不同类型的数据是如何通过不同种类的模式来识别和操作的。注意这里还涉及到了标准库中支持序列模式的一些具体类型如 `list`, `tuple`, `range`, `collections.deque` 等。 #### 复杂模式与守卫 除了基础的形式外,还可以附加额外的布尔表达式作为“守卫”,只有在满足这些条件下才会触发相应的行为。 ```python point = (1, 2) match point: case (x, y) if x > 0 and y > 0: quadrant = "First Quadrant" case (-x, y) if y > 0: quadrant = "Second Quadrant" case (_, _) : quadrant = "Other quadrants or axes." print(quadrant) ``` 在这个例子中,“守卫”帮助进一步细化了哪些坐标点属于哪个象限。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值