参考资料:
Python yield使用浅析:http://www.liaoxuefeng.com/article/001373892916170b88313a39f294309970ad53fc6851243000
问题源地址:https://www.zhihu.com/question/38868916
这两天稍微了解了一下python的生成器和匿名生成器,总结一下。
现在有一个问题:
让你展开一个嵌套若干列表的列表,例如[1,2,[3],[4,5,6,[7,8,[9]]]],然后要求是让你写一个生成器。返回的是1,2,3,4,5….
普通生成器的写法:
1 def release(root_l): 2 if isinstance(root_l,list): 3 for sub in root_l: 4 for i in release(sub): 5 yield i 6 else : 7 yield root_l
解释:
这个生成器就是递归的去匹配list,然后返回值。其中要注意的是第二层的for循环,容易出错。release(sub)返回的是一个生成器,而不是值,所以需要再打开这个生成器。
(不理解生成器的同学,可以去学习一下上面的链接,非常好的学习资料。)
匿名生成器的写法:
1 g=lambda x:(z for y in x for z in (isinstance(y,list) and g(y) or [y]))
解释:
在解释这个生成器前,先了解一下lambda函数的递归。
现在有个简单的问题:让你用匿名函数实现一个求阶乘的函数。
一种写法:
1 fac=lambda n: 1 if n<=1 else n*fac(n-1)
#也可以写成这样
2 f= lambda n: n and n*f(n-1) or 1
但是这种写法有一个问题,就是这个函数调用了全局变量fac,所以也可以写出这样的形式。
1 P=lambda self,n:n*self(self,n-1) if n>1 else 1
这样写的好处是不涉及全局变量,更深入的,没查到什么资料。
有了这个基础知识,就可以解释一下上面的匿名生成器了:
1 g=lambda x:(z for y in x for z in (isinstance(y,list) and g(y) or [y]))
解释:
首先先看最外层的两个‘()’。在python lambda中,用[]推导出来的是迭代器(Iterables),用()推导出来的是生成器(Generators)。
(参考:https://www.zhihu.com/question/24807364)
其他的就和普通的生成器一样了。
另外,对于这个问题,如果不用生成器写的话,还看到一个很好玩的写法。
1 f=lambda x:sum([f(s) if isinstance(s,list) else [s] for s in x],[])
最后,推荐一篇,在查资料的过程中意外的看到关于函数式编程的文章
http://blog.csdn.net/pongba/article/details/1336028
update:16-03-29
1 g=lambda x:(z for y in x for z in (isinstance(y,list) and g(y) or [y]))
1 a=[1,2,3,[4,5,6,[7,8,[9]]]] 2 3 g=lambda s:(isinstance(s,list) and y or s for x in isinstance(s,list) and s or [1] for y in isinstance(s,list) and g(x) or [1])