代码之家  ›  专栏  ›  技术社区  ›  LondonRob

用于检查列表是否包含元素的结构模式匹配

  •  0
  • LondonRob  · 技术社区  · 11 月前

    Boto3列出了这样无用的桶:

    {'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 哪个在存储桶列表的中间?你可能希望你能做到这一点:

    match s3_response:
        case {"Buckets": [*_, {"Name": "bar", "CreationDate": _}, *_]}:
            print("Bucket 'bar' found")
        case _:
            print("Bucket 'bar' not found")
    

    但这给出了:

    SyntaxError:序列模式中的多个星号名称

    当然,我可以用无聊的老方法做事,但这有什么乐趣呢:

    'bar' in [bucket.get("Name", "") for bucket in s3_response.get("Buckets", [])]
    
    1 回复  |  直到 11 月前
        1
  •  1
  •   jsbueno    11 月前

    中的匹配表达式 match..case Python中的语句有一种特殊的语法,即不是Python,因此所有可能的匹配都仅限于中列出的内容 PEP-0622 .

    这里提到的序列是:

    序列模式看起来像[A,*rest,b],类似于列表 打开包装。一个重要的区别是嵌套在其中的元素 它可以是任何类型的模式,而不仅仅是名称或序列。它 只匹配适当长度的序列,只要所有 子模式也匹配。它使其所有的绑定 子模式。

    因此,对于 in 接线员-很抱歉破坏了你的乐趣。你能得到的最好的结果是在你的 case -因为保护表达式在Python中再次有效:

    match s3_response:
        case {"Buckets": [*buckets] if any((bucket["Name"] == "bar" and "CreationDate" in bucket and len(bucket) == 2) for bucket in buckets):
            print("Bucket 'bar' found")