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 变量上。

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

 

 

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值