1、21-4 匿名函数及高阶函数CONTENTS目 录 1匿名函数map()23reduce()filter()45sorted()使用Python写一些执行脚本时,使用匿名函数可以省去定义函数的过程,让代码更加精简。对于一些抽象的,不会别的地方再复用的函数,有时候给函数起个名字也挺麻烦,使用匿名函数不需要考虑命名的问题,并且可以让代码更容易理解。匿名函数使用关键字lambda来定义,语法格式:lambda args:expression20.4.1匿名函数匿名函数20.4.1 匿名函数冒号前是参数,可以有多个,用逗号隔开,冒号右边可以是任意表达式,但不能是语句,例如不能是print。由于匿名函数
2、没有名称,不能直接调用,需要赋值给一个对象,然后依靠此对象来调用:a,b=3,4 f1=lambda x,y:x+y print f1(a,b)7上述代码的第二行等价于:def f1(x,y).return x+y匿名函数的主要意义在于函数速写,它也常常在map()、reduce()等高阶函数中作为参数来使用。map()函数和接下来要介绍的其他几个函数都是高阶函数。高阶函数的定义:函数的参数(同时也是函数要处理的对象)是其他函数。map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的列表返回。函数原型如下:map(function,it
3、erable,.)在map()的参数中,function是一个处理函数,iterable为一个或多个可迭代对象。map()会根据提供的函数对指定序列做映射,即以参数序列中的每一个元素调用function函数,返回包含每次function函数返回值的新列表。有一点需要注意的是,Python2返回列表,Python3返回一个map对象,你可以用for循环迭代它,取出其中的值。21.4.2map()21.4.2 map()map(f(x),list)123456789list:14916 25 36 49 64 81return:f(x)=x2 假设我们有一个函数f(x)=x2,要把这个函数作用在一
4、个包含数字19的列表对象上,用高阶函数map()来实现:def foo(x):return x*x map(foo,1,2,3,4,5,6,7,8,9)1,4,9,16,25,36,49,64,8121.4.2 map()map()函数不改变原有的列表,而是返回一个新的列表,利用map()函数,可以把一个列表转换为另一个列表,只需要传入转换函数。传入的函数可以是匿名函数,因此上面的代码可以写成以下形式:map(lambda x:x*x,1,2,3,4,5,6,7,8,9)1,4,9,16,25,36,49,64,8121.4.2 map()由于列表包含的元素可以是任何类型,因此,map()不仅
5、仅可以处理只包含数值的列表,事实上它可以处理包含任意类型的列表,只要确保传入的函数可以处理这种数据类型即可。因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个列表中所有的元素由数字转为字符串,只需要一行代码:map(str,1,2,3,4,5,6,7,8,9)1,2,3,4,5,6,7,8,9reduce()函数也是Python内建的一个高阶函数。reduce()函数会对参数序列中元素进行累积。函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给reduce中的函数function(有两个参数)先对集合中的第1、2个元素进行操作,得到的结果再与第三
6、个数据用function函数运算,最后得到一个结果。函数原型如下:reduce(function,iterable,initializer)参数function是用于处理的函数;iterable为可迭代对象;initializer是可选的,为初始参数,如果提供了initializer,就先用initializer和数据集中的第1个元素进行操作。返回值是函数计算结果。21.4.3reduce()21.4.3 reduce()reduce()函数接收的参数和map()类似,但行为和map()不同,reduce()把一个函数作用在一个序列x1,x2,x3.上,这个函数必须接收两个参数,reduce把
7、结果继续和序列的下一个元素做累积计算,其效果就是:reduce(f,x1,x2,x3,x4)等价于 f(f(f(x1,x2),x3),x4)比方说对一个序列求累计乘积,就可以用reduce实现。下面是利用reduce()求阶乘结果的例子:a=1n=input(Enter a Number(n=1):)if n=1:a=reduce(lambda x,y:x*y,range(1,n+1)print a执行结果Enter a Number(n=1):672021.4.3 reduce()多了解reduce函数后,我们会发现它非常使用且方便,比如要把序列1,3,5,7,9变换成单一的整数13579,
8、reduce也可以派上用场:def fn(x,y):return x*10+y reduce(fn,1,3,5,7,9)1357921.4.3 reduce()考虑到字符串str也是一个序列,对上面的例子稍加改动,配合map(),我们也可以写出把str转换为int的函数:def fn(x,y):return x*10+y def char2num(s):return 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9s reduce(fn,map(char2num,13579)1357921.4.3 reduce()整理成一个单一的转换函数就是:def str2in
9、t(s):if s.isdigit():def fn(x,y):return x*10+y def char2num(s):return 0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9s return reduce(fn,map(char2num,s)else:print Need a numeric string.也就是说,假设Python没有提供int()函数,你完全可以自己写一个把字符串转化为整数的函数,而且非常简单。注意,reduce()函数在Python2是内建函数,从Python3开始移到了functools模块。Python内建的filter()函
10、数用于过滤序列。和map()类似,filter()也接收一个函数和一个序列。和map()不同的时,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。函数原型如下:filter(function,iterable)function为判断函数,iterable为可迭代对象。对于其返回值,Python 2中返回的是过滤后的列表,而Python 3中返回到是一个可迭代的filter类,相对Python2提升了性能,可以节约内存。21.4.4filter()21.4.4 filter()下面举个例子,在一个list中,删掉偶数,只保留奇数:de
11、f is_odd(n):.return n%2=1 filter(is_odd,1,2,4,5,6,9,10,15)1,5,9,15再举例把一个序列中的空字符串删掉:def not_empty(s):.return s and s.strip()filter(not_empty,A,B,None,C,)A,B,C可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个字典呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数
12、抽象出来。通常规定,对于两个元素x和y,如果认为x y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。21.4.5sorted()21.4.5 sorted()Python内置的sorted()函数对所有可迭代的对象进行排序操作。函数原型:sorted(iterable,cmp,key,reverse)iterable:可迭代对象。cmp:比较的函数,这个具有两个参数,参数的值都是从可迭代对象中取出,此函数必须遵守的规则为,大于则返回1,小于则返回-1,等于则返回0。key:指定一个函数,每个元素先被此函数处理,然后再参与排序。reverse:排序规则,rever
13、se=True 降序,reverse=False 升序(默认)。返回值:排序后的列表。21.4.5 sorted()默认情况下,对字符串排序,是按照ASCII的大小比较的,因此所有的大写字母会排在所有的小写字母之前。现在,我们提出排序应该忽略大小写排序。忽略大小写来比较两个字符串,实际上就是先把字符串都变成大写(或者都变成小写),再进行比较。因此,要实现这个算法,不必对现有代码大加改动,只要通过参数key指定一个str.lower()或upper()方法即可。s1=It is never too old to learn sorted(s1.split(),key=str.lower)is,It,learn,never,old,to,too从上述例子可以看出,高阶函数的抽象能力是非常强大的,而且,核心代码可以保持得非常简洁。