1、匿名函数与lambda
Python可以使用lambda关键字创建匿名函数。其表达式形式如下:
lambda [arg1[,arg2,...argN]]:expression 其中参数可选
上述lambda表达式返回一个可调用的函数对象
例如:
def true():return True ---> lambda :True
但一个lambda函数自己就是无目的的服务的,上面我们简单地用lambda
创建一个函数对象,但是既没有在任何地方保存,也没有调用。这个
函数对象的引用计数在函数创建时被设置为True,但是因为没有引用
保存下来,计数又回到零,然后被垃圾回收掉了。
>>>true = lambda : True
>>>true() True
如上:可以将它保存在一个变量中。下面是带参的匿名函数
def add(x,y):return x+y ---> lambda x,y:x+y
def add(x,y=2):return x+y ---> lambda x,y=2:x+y
def show(*z):return z ----> lambda *z : z
lambda 看起来是函数的单行版本,但是他不等于c++的内联函数,
这种语句的目的是由于性能的原因,在调用时绕开函数的栈分配。
2、内建函数filter()\map()\reduce()
filter(func,seq) 调用func来遍历每个seq中的元素,过滤掉不满足func
的元素,返回满足func的元素。
map(func,seq1[,seq2...]) 将函数func作用于给定序列的每个元素,
并用一个列表来提供返回值
reduce(func,seq[,init]) 将func作用于seq序列的元素,每次携带一对
参数先是两个元素,在就是上两个元素的结果与下一
个元素。
例:
>>> allNums = [1,2,3,4,5,6]
>>> filter(lambda n: n%2,allNums)
[1,3,5]
>>> map(lambda n: n%2,allNums)
[1,0,1,0,1,0]
>>> reduce(lambda x,y:x+y,allNums)
21
需要注意的几点:
1、简化代码:
from random import randint
def odd(n):
return n%2
allNums = []
for eachNum in range(9):
allNums.append(randint(1,99))
print filter(odd,allNums)
--->
from random import randint as ri
print [n for n in [ri(1,99) for i in range(9)] if n%2]
2、带多个系列的map例子
>>> map(lambda x,y:x+y,[1,3,5],[2,4,6]
[3,7,11]
使用None的函数对象
>>> map(None,[1,3,5],[2,4,6])
[(1,2),(3,4),(5,6)]
可以将不相关的序列归并在一起。
3、偏函数应用
currying的概念将函数式编程的概念和默认参数以及可变参数结合在一起。
关键字是partial,将一个带n个参数的函数,固化一个参数,并返回
另n-1个参数,如:
>>> add1 = partial(add,1)
>>> add1(3)
4
使用partial前,需要在functools中导入它
>>> from functools import partial
第二个例子:将二进制(字符串形式)转换成为整数
>>> baseTwo = partial(int,base=2)
>>> baseTwo.__doc__='Convert base 2 string to an int.'
>>> baseTwo('10')
2
第二个例子中,我们知道它实现的是int('10',2)的功能,此处base
关键字起了很大的作用,去掉base关键字,上述表达式将被解释为
int(2,'10)---> 明显是错误的。关键字放置在恰当的位置,顺序就
固定下来。
4、生成器
生成器的一个作用是协同程序是可以运行的独立函数调用,可以暂停或者
挂起,并从离开的地方继续执行。其关键字是yield。
一个简单的生成器:
def simpleGen():
yield 1
yield '2 --> punch!'
调用上面的生成器函数,获得并保存一个生成器对象
>>> myG = simpleGen()
>>> for eachItem in simpleGen():
print eachItem
1
'2 --> punch!'
带序列并从序列中返回一个随机元素的随机迭代器:
from random import randint
def randGen(aList):
while len(aList)>0:
yield aList.pop(randint(0,len(aList)))
>>> randGen(['rock','paper','scissor'])
生成器的send()\close()
例子:
def counter(start_at = 0):
count = start_at
while True:
val = (yield count)
if val is not None:
count = val
else:
count += 1
>>> count = counter(5)
>>> count.next()
5
>>> count.next()
6
>>> count.send(9)
9
>>> count.close()