高阶函数

一、函数名即变量

>>> abs(-10)
10
>>> abs
<built-in function abs>
# 将函数执行的结果赋值给变量
>>> x = abs(-10)
>>> x
10
# 将函数名直接赋值给变量,该变量f就指向函数abs
>>> f = abs
>>> abs
<built-in function abs>
>>> f
<built-in function abs>
# 指向函数的变量可以直接当做函数来调用
>>> f(-10)
10
>>> 

如果将函数名当做变量来使用时,就会出现函数无法再调用的情况,因此这种情况是危险的:

>>> abs
<built-in function abs>
>>> abs = 10
>>> abs
10
>>> abs(-10)
Traceback (most recent call last):
  File "<pyshell#90>", line 1, in <module>
    abs(-10)
TypeError: 'int' object is not callable
>>> 

 

二、高阶函数:一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数。

既然变量可以指向函数,而函数的参数又可以接收变量,因此函数的参数也就可以接收函数名,也即可以接收函数作为参数,称为高阶函数:

# f是一个函数名,x和y是参数变量
>>> def add(x,y,f):
    return f(x)+f(y)
>>>
验证结果如下:
>>> add(-5,6,abs)
11
>>> 

将可变参数作为函数名传递多个函数:

>>> def some(x,*fs):
    s = [f(x) for f in fs]
    return s
>>> print(some(2,bin,oct,hex,int,abs,sqrt))
['0b10', '0o2', '0x2', 2, 2, 1.4142135623730951]
>>> 

 三、一些内建函数

1)map():map函数接收两个参数,第一个是函数,第二是Iterable,map将Iterable的每一个元素作为传入函数的参数,并最终将结果作为新的Iterator返回。

>>> def f(x):
    return x * x

>>> r = map(f,[1,2,3,4,5,6,7,8,9,10])
>>> r
<map object at 0x000002013190B6D8>
>>> map
<class 'map'>
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
>>> s = map(str,[1,2,3,4,5,6,7,8,9,10])
>>> list(s)
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
>>> 

 

 2)reduce():reduce函数接收两个参数,第一个是函数,第二个是序列(包含Iterable和Iterator),函数的参数需要同时接收两个参数,reduce计算完两个参数后,继续和下一个元素做累积运算。

其效果如下:reduce(f,[x1,x2,x3,x4]) = f(f(f(x1,x2),x3),x4),可以很方便的进行迭代运算。

>>> from functools import reduce
>>> def add(x,y):
    return x + y
# 对一个序列进行求和运算:
>>> reduce(add,[1,3,4,5,9])
22
>>> 
>>> def fn(x, y):
    return x * 10 + y
# 将一个序列转换为整数
>>> reduce(fn,[1,3,5,7,9])
13579
>>> 

 

reduce函数和map函数结合的使用:将字符串转换成10进制数,也就是内建函数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':9}[s]

>>> reduce(fn,map(char2num, '13579'))
13579

 

将上述几个函数整理为一个函数:
>>> def str2int(s):
    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':9}[s]
    return reduce(fn,map(char2num,s))

>>> str2int('123456')
123456

3)filter(), 接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素,最终返回filter生成器。

 

# 通过filter()函数过滤偶数
>>> def is_odd(n):
    return n % 2 == 1
>>> L1 = filter(is_odd,[1,2,3,4,5,6,7,8,9,10])
>>> list(L1)
[1, 3, 5, 7, 9]
>>> 

# 通过filter()函数过滤奇数
>>> def not_odd(n):
    return n % 2 == 0
>>> L2 = filter(not_odd,[1,2,3,4,5,6,7,8,9,10])
>>> list(L2)
[2, 4, 6, 8, 10]
>>> 

# 过滤序列中的假值,包含空格、None、空序列。
>>> def false_filter(s):
    return s and s.strip()
>>> L3 = filter(false_filter,['A',' ',None,'','B','  ',[],(),{}])
>>> list(L3)
['A', 'B']
>>> 

 

 

 

 

 

*********************************************************************

 练习题

 *********************************************************************

1、利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart'];

# 自定义一个将字符串首字母大写的方法1:
>>> def normalize(name):
    name = name.lower()
    name = name[0].upper() + name[1:] 
    return name
# 自定义一个将字符串首字母大写的方法2:
>>> def normalize(name): 
    return name.title()

>>> L2 = list(map(normalize,L1))
>>> L2
['Adam', 'Lisa', 'Bart', 'Bob']

# 上面的方法类似于string模块中的capwords函数:
>>> from string import capwords
>>> L2 = list(map(capwords,L1))
>>> L2
['Adam', 'Lisa', 'Bart', 'Bob']
>>> 

 2、Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积;

>>> from functools import reduce
>>> def prod(L):
    return reduce(lambda x,y : x * y, L)
>>> print('3 * 4 * 5 * 6 = ',prod([3,4,5,6]))
3 * 4 * 5 * 6 =  360
>>> 

3、利用mapreduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456;

>>> from functools import reduce
>>> def str2float(s):
    '''
    1、先找出字符串中的'.'的index;
    2、根据index算出float小数点后有几位;
    3、将小数点前和小数点后的数连接在一起后算出一个int值;
    4、根据小数的位数除以对应的10的次方数即可得出float数。
    '''
    def str2num(s):
        return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s]
    def str2int(x,y):
        return x * 10 + y
    pointIndex = s.find('.')
    pointNum = len(s) - pointIndex - 1
    s = s.replace('.','')
    return reduce(str2int,map(str2num,s))/(10**pointNum)

>>> str2float('123.456')
123.456
>>> 

 

posted @ 2016-04-10 20:12  疯狂的杰瑞  阅读(655)  评论(0编辑  收藏  举报