高阶函数

本文转自:https://blog.csdn.net/qq_43463045/article/details/105098786

 

以下函数皆是Python内置的函数

  • 什么是高阶函数
  • map
  • filter
  • reduce
  • 小结
  • 参考文档

什么是高阶函数

一个函数作为一个参数传入另一个函数,这个被传入参数的函数可以称为高阶函数;
一个函数的返回值也是个函数,这个函数也可以称为高阶函数(返回值是自身,则为递归函数)

map

官方文档

map(function, iterable, …)
Return an iterator that applies function to every item of iterable, yielding the results. If additional iterable arguments
are passed, function must take that many arguments and is applied to the items from all iterables in parallel. With multiple
iterables, the iterator stops when the shortest iterable is exhausted. For cases where the function inputs are already arranged
into argument tuples, see itertools.starmap().

可见,map接受的参数是一个函数和一个可迭代对象,map的作用是返回一个迭代器,将函数作用于可迭代对象的每一个元素,然后返回结果(Python3中,返回的是map对象,可以用list,tuple,set等查看或应用)。

用法举例

 1 # 求一个列表每个元素的平方,生成新的列表
 2 mlist = [x for x in range(5)]
 3 def square(x):
 4     return x*x
 5 
 6 res = map(square, mlist)
 7 print(res, type(res))  # <map object at 0x10f23b048> <class 'map'>
 8 print(list(res))  # [0, 1, 4, 9, 16]
 9 
10 # 当然,这种简单的函数可以用匿名的函数代替
11 res = map(lambda x: x*x, mlist)
12 
13 # 用map函数可以求字符串每个单词的长度
14 mstr = "love yourself first"
15 wordlength = list(map(lambda x: len(x), mstr.split()))
16 print(wordlength)  # [4, 8, 5]

filter

官方文档

filter(function, iterable)
Construct an iterator from those elements of iterable for which function returns true. iterable may be either a sequence, a container which supports iteration, or an iterator. If function is None, the identity function is assumed, that is, all elements of iterable that are false are removed.
Note that filter(function, iterable) is equivalent to the generator expression (item for item in iterable if function(item)) if function is not None and (item for item in iterable if item) if function is None.
See itertools.filterfalse() for the complementary function that returns elements of iterable for which function returns false.

可以看出,filter接受的参数也是一个函数和一个可迭代对象。
它的作用是构建一个迭代器,这个迭代器里的元素是函数作用于可迭代对象里的元素返回t为rue的元素构成的。这么说有点绕,简单理解就是,用传入的这个函数作用于可迭代对象的每个元素,返回为true则“保留”(实际上传入的iterable不变),反之则“舍弃”。
注意到文档说,如果function是None,那么可迭代对象里的false值都会被“舍弃”,相当于下面生成器:

(item for item in iterable if item)

如果function不是None,则相当于以下生成器:

(item for item in iterable if function(item))

既然filter函数返回的对象相当于生成器对象,那么也可以用next()方法取出其中的值。

用法举例

# 验证
mylist = [0, 1, 2, 3, 4]
gen_list_none = (x for x in mylist if x)
fil_list_none = filter(None, mylist)
print(gen_list_none, list(gen_list_none))  # <generator object <genexpr> at 0x1014189a8> [1, 2, 3, 4]
print(fil_list_none, list(fil_list_none))  # <filter object at 0x101439ef0> [1, 2, 3, 4]

def even_num(x):
    return x % 2 == 0
gen_list = (x for x in mylist if even_num(x))
fil_list = filter(even_num, mylist)
print(gen_list, list(gen_list))  # <generator object <genexpr> at 0x101418a20> [0, 2, 4]
print(fil_list, list(fil_list))  # <filter object at 0x101452080> [0, 2, 4]
# 可以看出,当function为None的时候,0被“过滤”掉了

# 求2-50之间的素数
def pri_num(x):
    for i in range(2, x):
        if x%i == 0:
            return False
    return True

fil_pri = list(filter(pri_num, range(2, 50)))
print(fil_pri)
# [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
# 不难发现,等价于(x for x in range(2, 50) if pri_num(x)),有兴趣的可以自己下去尝试,也可以试着用next()函数取值。

reduce

这个函数在Python3中被移出了built-in函数库,放在了funtools里。在Python3中调用的时候需要导入。
在Python2.7 的官方文档里,reduce()的说明如下:

Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a 
single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is
the accumulated value and the right argument, y, is the update value from the iterable. If the optional initializer is present,
it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If
initializer is not given and iterable contains only one item, the first item is returned. Roughly equivalent to:
def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        try:
            initializer = next(it)
        except StopIteration:
            raise TypeError('reduce() of empty sequence with no initial value')
    accum_value = initializer
    for x in it:
        accum_value = function(accum_value, x)
    return accum_value

reduce的作用官方文档已经说得很清楚了,我解释下后半段,initalizer值的问题,这个意思是说reduce的初始值,例如计算1-4累积的时候,默认没有初始值,计算结果是24,如果初始值是2,则计算过程为21234 ->48

用法举例

# reduce一般用于计算累积累和之类的操作
from functools import reduce
# 计算1-5的累积
cumu_num = reduce(lambda x, y:x*y, range(1, 6))

# 计算0-100内偶数的累和
even_nums = (x for x in range(101) if x%2 ==0)
cumu_evennum = reduce(lambda x,y:x+y, even_nums)

小结
map和filter,返回值分别是map和filter对象,用list、tuple、set等转换成相应的对象可以更方便的使用;
reduce的返回值是计算的结果;
这三个高阶函数通常搭配lambda函数使用,如果遇到逻辑比较复杂的函数,不建议使用匿名函数,毕竟匿名函数的初衷是方便逻辑比较简单的函数的使用。

posted @ 2022-03-07 21:18  八戒不爱吃西瓜  阅读(112)  评论(0编辑  收藏  举报