今天在弄我的语法分析器的时候,为了观察结果,我想找一个压平嵌套列表的函数(我写了个但是不太满意,记得cnblogs有看到过),于是搜了一下,找到了这篇文章:
http://www.cnblogs.com/c-hy/archive/2012/09/21/2696703.html
里面的lambda函数让我很满意,但是有个用法确实第一次见,函数如下:
flat=lambda L: sum(map(flat,L),[]) if isinstance(L,list) else [L,]
注意里面的一个用法, x if y else z
这个用法的效果是,如果y真,返回x,否则返回z。
而且这个用法是表达式,不是语句!
可以算是一个语法糖,从上面可以看到,通过赋值lambda实现了递归(一次可以实现变向的循环),通过这个语法糖又实现了选择,因此极大增强了lambda的威力。可惜就是不赋值的话,还是实现不了递归,希望能够有所改进,但是现在已经很接近lisp的表达能力了。
这个用法是表达式,并不局限与lambda语句内的。
因此我们可以这样写:
x=3*4/7
y='a'
z='b'
t=y if int(x) else z
最后提供两个lambda函数:
#解包函数,将递归的解包,直到参数是原子或者长度大于1的列表
wrap=lambda L: tuple(wrap(list(L))) if isinstance(L,tuple) else L if not isinstance(L,list) else map(wrap,L) if len(L)>1 else wrap(L[0])
#压平列表,对元组也会进行压平,但仍返回元组
flat=lambda L: sum(map(flat,L),[]) if isinstance(L,list) else [tuple(flat(list(L))),] if isinstance(L,tuple) else [L,]
ps:我才意识到,python的while、for、try也可以接else子句,受教育了
补充,lambda的匿名递归方法,lambda也可以实现递归的,方法是利用参数默认值来实现赋值的命名操作,从而保证函数的匿名性。
(lambda n,s=lambda n,f:1 if n<2 else f(n-1,f)*n:s(n,s))(10)