如何用Python结构模式匹配检查列表中是否包含指定元素?
用Python结构模式匹配检查S3桶列表中是否存在指定元素(非首尾位置)
假设Boto3返回的S3桶列表数据如下:
{'Buckets': [{'CreationDate': datetime.datetime(1, 1, 1, 0, 0, tzinfo=tzlocal()), 'Name': 'foo'}, {'CreationDate': datetime.datetime(1, 1, 1, 0, 0, tzinfo=tzlocal()), 'Name': 'bar'}, {'CreationDate': datetime.datetime(2024, 7, 30, 15, 4, 59, 150000, tzinfo=tzlocal()), 'Name': 'baz'}], 'Owner': {...}}
要判断桶foo是否在列表开头,可以用结构模式匹配实现:
match s3_response: case {"Buckets": [{"Name": "foo", "CreationDate": _}, *_]}: print("Bucket 'foo' found") case _: print("Bucket 'foo' not found")
同理,判断桶是否在列表末尾只需调整模式,把*_放在目标元素前面即可。
但如果要判断桶bar是否存在于列表中间(非首尾位置),直接写[*_, {"Name": "bar", ...}, *_]会触发语法错误:
SyntaxError: multiple starred names in sequence pattern
这是因为Python的结构模式匹配不允许在同一个序列模式中使用多个*_捕获。不过可以通过以下几种方式用结构模式匹配实现需求:
方法1:结合守卫条件匹配
先匹配整个Buckets列表,再在守卫条件里检查元素是否存在且不在首尾:
match s3_response: case {"Buckets": buckets} if len(buckets) >= 2 and any(b["Name"] == "bar" for b in buckets[1:-1]): print("Bucket 'bar' found in middle") case _: print("Bucket 'bar' not found in middle")
方法2:递归模式匹配
通过递归检查剩余元素,实现对中间位置的匹配:
match s3_response: case {"Buckets": [_, *rest]}: match rest: case [{"Name": "bar", "CreationDate": _}, *_]: print("Bucket 'bar' found in middle") case [_, *more]: # 递归检查剩余部分 s3_response["Buckets"] = rest continue case _: print("Bucket 'bar' not found in middle") case _: print("Bucket 'bar' not found in middle")
方法3:组合多模式覆盖场景
如果列表长度有限,可以组合多个模式覆盖所有可能的中间位置:
match s3_response: case {"Buckets": [_, {"Name": "bar", "CreationDate": _}, *_]} | \ {"Buckets": [_, _, {"Name": "bar", "CreationDate": _}, *_]}: print("Bucket 'bar' found in middle") case _: print("Bucket 'bar' not found in middle")
当然,传统的列表推导式方法依然简洁高效:
'bar' in [bucket.get("Name", "") for bucket in s3_response.get("Buckets", [])[1:-1]]
内容的提问来源于stack exchange,提问作者LondonRob
相关产品推荐
相关产品推荐

