Python高阶函数Higher-order function
1.函数式编程
函数
是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。而
函数式编程
——Functional Programming
,虽然也可以归结到面向过程的程序设计,但其思想更接近抽象的计算。我们首先要搞明白计算机(
Computer
)和计算(Compute
)的概念。
在计算机的层次上,CPU
执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言
是最贴近计算机的语言。
而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件
越远。对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如
C
语言;越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Python
语言。函数式编程就是一种抽象程度很高的编程范式。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python
对函数式编程提供了部分支持。由于Python
允许使用变量,因此,Python
不是纯函数式编程语言。
- 变量可以指向函数
例如Python内置求绝对值函数abs()
>>> abs(-5)
5
>>> f = abs
>>> f
<built-in function abs>
可以看见,只写abs
只是函数本身,而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 "<pyshell#23>", 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
2.引出高阶函数
上面的例子,函数可以传参数,而函数名可以做变量,那我们函数里面的参数也可以为函数名。
代码中的total
为高阶函数
# -*- coding: utf-8 -*-
# @File : 引出高阶函数.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 10:00
def fun(i):
return i * 2
def total(x, y, fun):
return fun(x) + fun(y)
add_sum = total(1, 2, fun)
print(add_sum) # 6
下面代码test
称为高阶函数
# -*- coding: utf-8 -*-
# @File : 高阶函数.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 10:12
def fac(n): # 定义一个递归函数计算阶乘
if n == 1: # 递归终止条件
return 1
else:
# 在test()函数的函数体内调用该本身
return n*fac(n-1) # 递归调用
def test(list_, fun): # 将函数fac本身作为参数传进来,test称为高阶函数
new_list = []
for x in list_:
new_list.append(fun(x))
print(new_list)
ls = [1, 2, 3, 4, 5, 6, 7]
test(ls, fac) # 调用函数test 并把参数lst和fac传入
3.Python内置高阶函数
# -*- coding: utf-8 -*-
# @File : 内置高阶函数.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 14:10
from functools import reduce
'''
1.map函数:把一个可迭代对象中的每个元素转换为一个新的对象,最后返回一个新的可迭代对象'''
# map(fun, iterables)
lst = [1, 2, 3, 4, 5]
ite = map(lambda x: x ** 2, lst)
print(ite) # <map object at 0x000002A24AF06970>
for i in ite:
print(i, end=' ') # 1 4 9 16 25
'''
2.reduac() 把一个可迭代对象中的每个元素都做聚合处理,返回一个聚合之后的值
from functools import reduce
reduce(function, sequence[, initial]) -> value'''
# function:一共有两个参数的函数
# sequence:是一个序列,是一些数据的集合,或者是一组数据,可迭代对象
# initial:可选,初始参数 返回值:返回函数计算的结果
va = reduce(lambda x, y: x + y, lst) # 求累加
print('\ns =', va) # s = 15
def max_(x, y):
if x > y:
return x
max1 = reduce(max_, iter((3, 2))) # 求最大值
print(max1) # 3
'''
3.filter 把一个可迭代对象中的元素做过滤操作,若果func返回值为True是留下,否则过滤掉'''
staff = [
{'name': '张三', 'age': 18, 'salary': 2000},
{'name': '李四', 'age': 20, 'salary': 4000},
{'name': '麻子', 'age': 22, 'salary': 6000}]
# 过滤留下大于18岁的员工
lst_age = filter(lambda x: x['age'] > 18, staff)
print('大于18岁的员工:', list(lst_age))
# 工资大于4000的员工
lst_salary = filter(lambda x: x['salary'] > 4000, staff)
print('工资大于4000的员工:', list(lst_salary))
'''
4.max 和 min'''
# 计算最大工资的员工
print('最高工资的员工:', max(staff, key=lambda x: x['salary']))
# 计算最小年龄的员工
print('最低工资的员工:', min(staff, key=lambda x: x['age']))
'''
5.sorted把一个迭代对象里的每个元素做排序,最终返回一个列表'''
# 根据员工年龄降序排序
list_sorted = sorted(staff, key=lambda x: x['age'], reverse=True)
print('工资降序排序:', list_sorted)
4.map
函数
map()
函数,把一个可迭代对象中的每一个元素换成一个新的对象,最终返回一个迭代器
。
Python内置map()
函数:
class map(object):
"""
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __init__(self, func, *iterables): # real signature unknown; restored from __doc__
pass
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass
map()
函数的返回值:
map(func, *iterables) --> map object
参数详解:
"""
func:代表传入参数为函数,这里的函数指定指向函数的函数名
*iterables:代表参数指定的可迭代的
返回值:返回处理好的数据
map()函数:是将传入的func函数作用于可迭代的数据里的面每个元素,并将处理好的新的结果返回
"""
代码实现
# -*- coding: utf-8 -*-
# @File : map函数.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 10:03
lst = [1, 2, 3, 4, 5]
ite = map(lambda x: x**2, lst)
print(ite) # <map object at 0x000002A24AF06970>
for i in ite:
print(i, end=' ')
5.聚合函数reduce
reduce()
函数,把一个可迭代对象中的每个元素做聚合处理,最终返回一个聚合之后的值.
functools
函数reduce()
def reduce(function, sequence, initial=_initial_missing):
"""
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
"""
it = iter(sequence)
if initial is _initial_missing:
try:
value = next(it)
except StopIteration:
raise TypeError("reduce() of empty sequence with no initial value") from None
else:
value = initial
for element in it:
value = function(value, element)
return value
try:
from _functools import reduce
except ImportError:
pass
reduce
函数的参数与返回值:
注意使用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 函数运算,最后得到一个结果。
"""
代码实现:
# -*- coding: utf-8 -*-
# @File : 聚合函数reduce.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 12:48
from functools import reduce
lst = [1, 2, 3, 4, 5]
va = reduce(lambda x, y: x+y, lst) # 求累加
print('s =', va)
def max_(x, y):
if x > y:
return x
max1 = reduce(max_, iter((3, 2))) # 比较大小求大值
print(f'max = {max1}')
6.过滤器filter
函数
filter()
函数 把一个可迭代对象中的元素做过滤操作,如果func
返回值为True
则留下,否则过滤掉。
Python内置的filter()
函数用于过滤序列,和map()
类似,filter()
也接收一个函数和一个序列,但是不同的是filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定元素的保留与丢弃。
Python内置函数filter()
class filter(object):
"""
filter(function or None, iterable) --> filter object
Return an iterator yielding those items of iterable for which function(item)
is true. If function is None, return the items that are true.
"""
def __getattribute__(self, *args, **kwargs): # real signature unknown
""" Return getattr(self, name). """
pass
def __init__(self, function_or_None, iterable): # real signature unknown; restored from __doc__
pass
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass
@staticmethod # known case of __new__
def __new__(*args, **kwargs): # real signature unknown
""" Create and return a new object. See help(type) for accurate signature. """
pass
def __next__(self, *args, **kwargs): # real signature unknown
""" Implement next(self). """
pass
def __reduce__(self, *args, **kwargs): # real signature unknown
""" Return state information for pickling. """
pass
参数列表:
filter(function, iterable)
"""
function:判断函数。
iterable:序列,(可迭代对象)。
返回值:返回列表
filter函数,序列(可迭代对象)的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返 回 True 的元素放到新列表中
"""
filter
函数实现过滤奇数:
# -*- coding: utf-8 -*-
# @File : filter函数.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 13:06
def not_odd(num):
return num % 2 == 0
# 过滤奇数
new_lst = filter(not_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(list(new_lst))
这里定义了一个函数not_odd
,不是奇数的函数,这个函数,只有当参数为2的整数倍时返回True
。这里
filter
函数的两个参数第一个是过滤方法,第二个是需要过滤的列表,将列表里面的元素依次带入函数中进行运算,得到的结果如果为True
时,将此结果作为新的filter
对象保留,等待函数里面的列表执行完成后,返回最终的值,这里的值为列表
,也就是过滤掉了False
的数据或元素。
filter
函数过滤操作
# -*- coding: utf-8 -*-
# @File : filter函数.py
# @author: Flyme awei
# @email : Flymeawei@163.com
# @Time : 2022/8/21 13:06
# filter 把一个可迭代对象中的元素做过滤操作,若果func返回值为True是留下,否则过滤掉
staff = [
{'name': '张三', 'age': 18, 'salary': 2000},
{'name': '李四', 'age': 20, 'salary': 4000},
{'name': '麻子', 'age': 22, 'salary': 6000}]
# 过滤留下大于18岁的员工
lst_age = filter(lambda x: x['age'] > 18, staff)
print(list(lst_age))
# 过滤留下工资大于4000的员工
lst_salary = filter(lambda x: x['salary'] > 4000, staff)
print(list(lst_salary))