【问题标题】:Are there pattern matching functions in Python like this?Python中有这样的模式匹配函数吗?
【发布时间】:2012-08-08 05:29:41
【问题描述】:

我刚刚发现Racket中的pattern matching功能非常强大。

> (match '(1 2 3) [(list a b c) (list c b a)])

'(3 2 1)

> (match '(1 2 3) [(list 1 a ...) a])

'(2 3)

> (match '(1 2 3)
    [(list 1 a ..3) a]
    [_ 'else])

'else

> (match '(1 2 3 4)
    [(list 1 a ..3) a]
    [_ 'else])

'(2 3 4)

> (match '(1 2 3 4 5)
    [(list 1 a ..3 5) a]
    [_ 'else])

'(2 3 4)

> (match '(1 (2) (2) (2) 5)
    [(list 1 (list a) ..3 5) a]
    [_ 'else])

'(2 2 2)

在 Python 中是否有类似的语法糖或库可以做到这一点?

【问题讨论】:

    标签: python lisp scheme pattern-matching racket


    【解决方案1】:

    不,没有,python 的模式匹配只是这样的可迭代解包:

    >>> (x, y) = (1, 2)
    >>> print x, y
    1 2
    

    或者在函数定义中:

    >>> def x((x, y)):
        ...
    

    或者在 python 3 中:

    >>> x, *y = (1, 2, 3)
    >>> print(x)
    1
    >>> print(y)
    [2, 3]
    

    但是有一些external libraries实现了模式匹配。

    【讨论】:

      【解决方案2】:

      Python 没有内置的模式匹配功能,但有一些 Python 库使用统一实现模式匹配。

      根据您的第一个示例,可以使用 unification 库匹配模式:

      from unification import *
      
      a,b,c = var('a'),var('b'),var('c')
      matched_pattern = unify([1,2,3],[var('a'),var('b'),var('c')])
      if(matched_pattern):
          second_pattern = [matched_pattern[c],matched_pattern[b],matched_pattern[a]]
          print(second_pattern)
      else:
          print("The pattern could not be matched.")
      

      【讨论】:

        【解决方案3】:

        如果您愿意使用基于 Python 的语言(即使它们不是严格意义上的 Python),那么您可能会喜欢 Coconut。

        Cocunut 为 Python 增加了几个用于函数式编程的特性,包括模式匹配。

        case [1,2,3]:
            match (a,b,c):
                print((c,b,a))
        # (3,2,1)
        
        case [1,2,3]:
            match (1,) + a:
                print(a)
        # (2, 3)
        
        case [1,2,3]:
            match (1,) + a if len(a) == 3:
                print(a)
        else:
            print("else")
        # else
        
        case [1,2,3,4]:
            match (1,) + a if len(a) == 3:
                print(a)
        else:
            print("else")
        # (2,3,4)
        
        case [1,2,3,4,5]:
            match (1,) + a + (5,) if len(a) == 3:
                print(a)
        else:
            print("else")
        # (2,3,4)
        

        【讨论】:

          【解决方案4】:

          2020 快到了,我想说https://github.com/thautwarm/moshmosh

          你可以这样使用:

          • main.py

            import moshmosh
            import mypackage
            
          • mypackage的某个模块中

            # +pattern-matching
            with match([1, [2, (3, 4)]]): 
             if [a, [2, (_, 4)]]: 
                 print(a) # print 1
            

          也支持 IPython。

          并且来自 moshmosh 的模式匹配是可扩展的(__match__ 用于制作新模式)和快速(不应该比手写慢)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-03-12
            • 1970-01-01
            • 2015-03-29
            • 2012-01-25
            • 2016-04-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多