有没有办法使用 python 的“匹配”语句来测试 Iterable 是不是包含模式?

Posted

技术标签:

【中文标题】有没有办法使用 python 的“匹配”语句来测试 Iterable 是不是包含模式?【英文标题】:Is there a way to test if an Iterable contains a pattern using python's "match" statement?有没有办法使用 python 的“匹配”语句来测试 Iterable 是否包含模式? 【发布时间】:2021-08-10 16:04:56 【问题描述】:

这与新的 Python 3.10 测试版和新的 match 语法有关。 有没有办法检查一个模式是否简单地包含在一个迭代中?最明显的解决方案是简单地将两个通配符放在两边,但由于来自可迭代解包的解包语法,这会引发SyntaxError

有没有办法做到这一点? 注意:在numbers 周围使用诸如包装类之类的东西 在这个例子中会很好,只要它使用匹配块并且至少有点可读,但是我已经尝试过这个并且没有太大的成功

示例:

numbers = [1, 2, 3, 5, 7, 8, 9] #does not have to be a list, could be a class if needed

match numbers:
    # this just raises a SyntaxError, but I need a way to do something equivalent to this
    case [*_, (5 | 6), *_]:
        print("match!")

【问题讨论】:

使用 any() 怎么样? any() 不能用于 match 语句,也不能用于任何函数;你得到的确切错误是TypeError: called match pattern must be a type 使用旧版python:print any([not not re.match(pattern, str(n)) for n in numbers]) if 5 in numbers or 6 in numbers: 有什么问题? 【参考方案1】:

不,我们目前没有任何计划支持可迭代包含检查作为结构模式匹配语法的一部分。

用合法的 Python 重写示例的最佳方法是使用普通的 if 测试:

if any(i in (5, 6) for i in numbers):
    print("match!")

如果包含检查只是更复杂模式的一部分,您可以将其编写为警卫:

match something:
    case [pattern, capturing, numbers] if any(i in (5, 6) for i in numbers):
        print("match!")

当然,如果你有一个序列,也可以在已知索引处找到一个项目:

match numbers:
    case [_, _, _, 5 | 6, *_]:
        print("match at position 3!")
    case [*_, 5 | 6, _, _, _]:
        print("match at position -4!")

话虽如此......

在示例中使用诸如 numbers 周围的包装类之类的东西是可以的,只要它使用匹配块工作并且至少有点可读

...我想映射模式可以被破解来完成这项工作(前提是您的所有项目都是可散列的并且没有异常的相等规则):

match dict.fromkeys(numbers):
    case 5: _ | 6: _:
        print("match!")

不过,我强烈建议使用 if 表单。

【讨论】:

以上是关于有没有办法使用 python 的“匹配”语句来测试 Iterable 是不是包含模式?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 if 语句中将 stack.pop() 与数组(比如“标签”)进行比较? [关闭]

Python匹配语句并使用输入来提供它? [关闭]

调试where方法返回None

有没有办法在 SQL Select 语句中使用来自 JSON 对象的值?

Python:正则表达式单词匹配

有没有办法从 python 3.x 中的测试脚本隐藏登录凭据