> 文档中心 > 【Python函数式编程③】——Python高阶函数 map、reduce、filter

【Python函数式编程③】——Python高阶函数 map、reduce、filter


Python函数式编程–Python高阶函数

在这里插入图片描述


文章目录

  • Python函数式编程--Python高阶函数
    • @[TOC](文章目录)
    • 一、函数式编程
      • 1.什么是函数?
      • 2.什么是函数式编程?
      • 3.高阶函数
    • 二、map 函数
    • 三、reduce 函数
    • 四、filter 函数
    • 五、 max 和 min
    • 六、sorted 函数
    • 七、sum 函数

一、函数式编程

1.什么是函数?

函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。

2.什么是函数式编程?

而函数式编程(请注意多了一个“式”字)——Functional Programming,虽然也可以归结到面向过程的程序设计,但其思想更接近抽象的计算。

我们首先要搞明白计算机(Computer)和计算(Compute)的概念。

在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。

而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。

对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Python语言。

函数式编程就是一种抽象程度很高的编程范式。

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

Python对函数对函数式编程提供了部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

高阶函数英文叫Higher-order function。什么是高阶函数?我们来看代码
变量可以指向函数

例如Python内置求绝对值函数abs()

>>> abs(-5) 5>>> abs <built-in function abs>

可以看见,只写abc只是函数本身,而abs(-5)才是函数调用,实际我们如果需要函数的结果,可以将函数赋值给变量

例如:

>>> i = abs(-5) >>> i 5>>> f = abs >>> f <built-in function abs> >>> f(-5) 5

我们可以看到,我们将调用函数的结果,赋值给变量 i ,这样变量就可以打印出结果,如果将函数本身赋值给变量f ,那么变量也拥有这个函数的功能,这个变量将指向这个函数,使用变量 f ()来调用函数和直接调用abs()效果是一样的。

函数名也可以是变量

函数是由def定义,函数名,括号,括号参数,冒号,函数体组成那么函数名是什么尼,可以发现,函数名是指向函数的变量,例如abs()这个函数,可以将abs看成变量,它指向一个可以求绝对值的函数,如果把abs指向其他的对象,例如我们给abs赋值,那看看还会指向求绝对值的函数么

>>> abs = 5 >>> abs(-5) Traceback (most recent call last): File "", line 1, in <module>   abs(-5) TypeError: 'int' object is not callable >>> abs 5

TypeError: ‘int’ object is not callable 提示,类型错误,int类型是不可以被调用的,我们看到,abs这个变量被赋值5,然后使用abs(-5)调动函数,发现异常,此时abs变量指向的不是函数,而是一个int类型的 5 ,实际上,我们工作或是开发中写代码,是不能这么写的,由此可以看出函数名其实就是变量

注意:由于 abs 函数实际上是定义在 import builtins 模块中的,所以要让修改 abs 变量的指向在其它模块也生效可以使用

import builtins builtins.abs = 10

3.高阶函数

我们想到,函数可以传参数,而函数名可以做变量,那我们函数里面的参数,也可以传入函数名

# -*- coding: UTF-8 -*- # 文件名:fun_a.py ef fun(i):    return i * 2def total(x, y, fun):    return fun(x) + fun(y)add_sum = total(1, 2, fun)print(add_sum)  # 6

那我们可以看到,将函数作为参数,传给另一个函数就是高阶函数

二、map 函数

map()函数,把一个可迭代对象中的每一个元素换成一个新的对象,最终返回一个迭代器

来看一下map函数的返回值:

map(func, *iterables) --> map object

参数详解:

"""func:代表传入参数为函数,这里的函数指定指向函数的函数名*iterables:代表参数指定的可迭代的返回值:返回处理好的数据 map()函数:是将传入的func函数作用于,可迭代的数据里#面每个元素,并将处理好的新的结果返回"""

代码1:

def fun_a(x):return x*10list_a = map(fun_a, [1, 2, 3, 4, 5])list(lst_a)# [10, 20, 30, 40, 50]

map() 传入的第一个参数是 fun_a ,即函数对象本身。由于结果 list_a 是一个 Iterator , Iterator 是惰性序列,因此通过 list() 函数让它把整个序列都计算出来并返回一个list。

很多情况下,也可以使用for循环也可以解决问题,但实际上map作为高级函数,将运算抽象化,还可计算复杂的函数,例如将列表的元素int类型转换为int类型,只需要一行代码

list(map(str, [1, 2, 3, 4, 5]))# ['1', '2', '3', '4', '5']

代码2:

# map()函数,把一个可迭代对象中的每一个元素换成一个新的对象,最终返回一个迭代器lst = [1, 2, 3, 4, 5]new_lst = map(lambda x: x**2, lst)
print(new_lst)

【Python函数式编程③】——Python高阶函数 map、reduce、filter

for i in new_lst:    print(i, end=' ')    # 1 4 9 16 25 

三、reduce 函数

reduce()函数,把一个可迭代对象中的每个元素做聚合处理,最终返回一个聚合之后的值

我们来看一下map函数的参数与返回值,注意使用reduce函数时需要先导入

reduce函数是在 functools模块里面的

from functools import reduce reduce(function, sequence[, initial]) -> value

参数详解:

"""function:一个有两个参数的函数 sequence:是一个序列,是一些数据的集合,或者是一组数据,可迭代对象 initial:可选,初始参数 返回值:返回函数计算的结果 reduce()函数,使用function函数(有两个参数)先对集合中的sequence第 1、2 个元素进行操作,如果存在 initial参数,则将会以sequence中的第一个元素和initial作为参数,用作调用,得到的结果再与sequence中的 下一个数据用 function 函数运算,最后得到一个结果。"""

代码:

from functools import reduce list_a = [1, 2, 3, 4, 5] def fun_b(x, y): return x + y print(reduce(fun_b, list_a)) # 运算结果如下   15

依次按照顺序从列表list_a中提取两个元素作为参数,进入fun_b中进行运算,得到的结果,作为下次运算时的其中一个参数,再从列表中取出一个元素,再进行运算。
最终得到的结果是总和的计算。

四、filter 函数

filter()函数 把一个可迭代对象中的元素做过滤操作,如果func返回值为True则留下。否则过滤掉

Python内建的 filter() 函数用于过滤序列,和 map() 类似, filter() 也接收一个函数和一个序列
但是不同的是 filter() 把传入的函数依次作用于每个元素,然后根据返回值是 True 还是 False 决定元素的保留与丢弃

看一下filter的参数

filter(function, iterable)

参数列表

"""function:判断函数。 iterable:序列,(可迭代对象)。 返回值:返回列表 filter函数,序列(可迭代对象)的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返 回 True 的元素放到新列表中"""

代码:

def not_odd(num):    return num % 2 == 0new_lst = filter(not_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])print(list(new_lst))# 运算结果如下:# [2, 4, 6, 8, 10]

这里定义了一个函数not_odd,顾名思义,不是奇数的函数,这个函数,只有当参数为2的整数倍时返回True

这里filter函数的两个参数第一个是过滤方法,第二个是需要过滤的列表,将列表里面的元素依次带入函数中进行运算,得到的结果如果为True时,将此结果作为新的filter对象保留,等待函数里面的列表执行完成后,返回最终的值,这里的值为列表,也就是过滤掉了False的数据或元素。

1.用filter来计算素数

那可以用filter来计算素数,计算素数的其中一个方法是埃氏筛法。

给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去…

用Python来实现这个算法,我们先写一个生成器构造一个从3开始的无限奇数序列,首先偶数列先排除

def oddnum():    n = 1    while True: n += 2 yield 

写一个筛选的函数,这里使用了匿名函数,这个函数是返回一个判断,判断是否为可整除数

def undivisible(n):    return lambda x: x % n > 0

使用filter来过滤,不断返回素数的生成迭代

def primes():    yield 2    it = oddnum()    while True: n = next(it) yield n it = filter(undivisible(n), it)

一个基本的判断素数方法就产生了,这里我们需要手动结束一下

# 打印100以内的素数for i in primes():    if i < 100: print(i)    else: break 

好的我们来解释一下代码,看到我们这里用到了几个知识点

生成器与迭代器、匿名函数、filter函数,其中

第一段代码生成了以3开始的奇数序列

第二段代码自定义过滤函数,包含匿名函数,判断值的取余是否能被整除

第三段代码用来返回素数,这里先返回一个2为素数,因为偶数都被排除了所

以整除3为基础进行排除,将数据不断

地迭代生成,留下对应的素数序列。

那这里就对应的filter函数就是用来过滤的方法进行返回数

五、 max 和 min

def max(*args, key=None): # known special case of max    """    max(iterable, *[, default=obj, key=func]) -> value    max(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its biggest item. The    default keyword-only argument specifies an object to return if    the provided iterable is empty.    With two or more arguments, return the largest argument.    """    passdef min(*args, key=None): # known special case of min    """    min(iterable, *[, default=obj, key=func]) -> value    min(arg1, arg2, *args, *[, key=func]) -> value With a single iterable argument, return its smallest item. The    default keyword-only argument specifies an object to return if    the provided iterable is empty.    With two or more arguments, return the smallest argument.    """    pass
print(max(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))# 10print(min(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))# 1

六、sorted 函数

sorted()函数 把一个可迭代对象里面的每个元素做排序

def sorted(*args, **kwargs): # real signature unknown    """    Return a new list containing all items from the iterable in ascending order. A custom key function can be supplied to customize the sort order, and the    reverse flag can be set to request the result in descending order.    """    pass
print(sorted([1, 5, 2, 3, 10, 6, 8]))# 输出结果如下# [1, 2, 3, 5, 6, 8, 10]print(sorted([1, 5, 2, 3, 10, 6, 8], reverse=True))# 输出结果如下#[10, 8, 6, 5, 3, 2, 1]

七、sum 函数

sum()函数 求和

def sum(*args, **kwargs): # real signature unknown    """    Return the sum of a 'start' value (default: 0) plus an iterable of numbers When the iterable is empty, return the start value.    This function is intended specifically for use with numeric values and may    reject non-numeric types.    """    pass
print(sum([10, 8, 6, 5, 3, 2, 1]))# 35