我想在Python中的列表上进行一些模式匹配.例如,在Haskell中,我可以执行以下操作:
fun (head : rest) = ...
因此,当我传入一个列表时,head
将是第一个元素,rest
并将成为尾随元素.
同样,在Python中,我可以自动解压缩元组:
(var1, var2) = func_that_returns_a_tuple()
我想用Python中的列表做类似的事情.现在,我有一个返回列表的函数,以及执行以下操作的一大块代码:
ls = my_func() (head, rest) = (ls[0], ls[1:])
我想知道我是否能以某种方式在Python中用一行来代替,而不是两行.
据我所知,在没有引入另一个函数的情况下,没有办法使它成为当前Python中的单行,例如:
split_list = lambda lst: (lst[0], lst[1:]) head, rest = split_list(my_func())
但是,在Python 3.0中,用于可变参数签名和参数解包的专用语法也可用于此类通用序列解包,因此在3.0中您将能够编写:
head, *rest = my_func()
有关详细信息,请参阅PEP 3132.
首先,请注意函数式语言的"模式匹配"和你提到的元组的赋值并不是那么相似.在函数式语言中,模式用于给出函数的部分定义.所以f (x : s) = e
并不意味着采用参数的头部和尾部f
并e
使用它们返回,但这意味着如果参数f
是形式x : s
(对于某些x
和s
),则 f (x : s)
等于e
.
python的赋值更像是一个多重赋值(我怀疑这是它的初衷).所以,你写的,例如,x, y = y, x
以交换值x
和y
不需要一个临时变量(就像使用一个简单的赋值语句).这与模式匹配几乎没有关系,因为它基本上是"同时"执行x = y
和的简写y = x
.虽然python允许任意序列而不是逗号分隔列表,但我不建议调用此模式匹配.使用模式匹配,您可以检查某些内容是否与模式匹配; 在python任务中,你应该确保两边的序列是相同的.
为了做你似乎想要的事情,你通常(也在函数式语言中)使用辅助函数(如其他人所提到的)或者类似于let
或where
构造的东西(你可以将其视为使用匿名函数).例如:
(head, tail) = (x[0], x[1:]) where x = my_func()
或者,在实际的python中:
(head, tail) = (lambda x: (x[0], x[1:]))(my_func())
请注意,这与其他具有辅助功能的解决方案基本相同,只是这是您想要的单线程.然而,它不一定比单独的功能更好.
(对不起,如果我的答案有点过头了.我认为区分清楚很重要.)