高阶函数
函数式编程
函数是PY内置的一种封装, 把大段代码封装成一个个函数, 然后再一层层调用
面向过程的程序设计
而函数式编程,其思想更接近抽象的计算
函数式编程特点: 允许把函数作为参数传入另一个函数中或返回一个函数 (类似回调)
而计算则指数学意义上的计算, 越是抽象的计算, 离计算机硬件越远
越低级的语言, 越贴近计算机, 抽象程度低, 执行效率高, 比如C语言
越高级的语言, 越贴近计算, 抽象程度高, 执行效率低, 比如PY语言
高阶函数
高阶函数英文叫Higher-order function
引入部分
print(abs(-5), abs) # 5 <built-in function abs>
a1 = abs
print(a1, abs, id(a1), id(abs)) # PYC是一样的
# abs(-5) 是函数的调用 返回值 5 | 具有小括号的 就是函数的调用
# abs a1 都是变量名 其内存地址都一致(PYC, 交互式没测试) | 尝试对abs进行赋值, abs不能再作为函数进行调用
abs = 10
try:
print(abs(-5)) # 报错 (PYC: 'int' 对象不可调用)
except TypeError as e:
print(e) # 'int' object is not callable
# 这里a1还能作为原来abs调用
print(a1(-5)) # 5
# 不过还可以
import builtins # builtins是Python中的一个模块. 该模块提供对Python的所有 "内置" 标识符的直接访问
print(builtins.abs(-5))
print('-' * 80)
高阶函数的定义
# 定义一个函数, 传入一个正整数数字元素的列表, 返回一个新列表 (该列表元素是之前数字元素的阶乘)
def b1(n): # 计算数字的阶乘
if n <= 1:
return 1
else:
return n * b1(n - 1)
# 这就是高阶函数
def b2(a, b):
c = a
c = [b(_) for _ in c]
return c
c1 = [1, 2, 3, 4, 5, 6, 7] # 原列表并没有改变
print(b2(c1, b1), c1)
匿名函数
没有名字, 也不算有函数体的函数(只有一句表达式)
功能比较单一
# 计算2个数字的和
a = lambda b, c: b + c # 把匿名函数赋值给一个变量 这样就可以调用
print(a, type(a)) # <function <lambda> at ...> <class 'function'>
print(a(3, 5))
内置高阶函数 map
返回一个将 function 应用于 iterable 中每一项并输出其结果的迭代器
如果传入了额外的 iterable 参数, function 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项
当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束
文档
map(func, *iterables) –> map object
# map(func, *iterables) –> map object
a3 = [1, 2, 3, 4, 5]
b3 = lambda _: _ ** 2
c3 = map(b3, a3)
e3 = list(c3) # 直接转为列表 | 转换前不能进行改变游标
print(a3, b3, c3, e3) # [1, 2, 3, 4, 5] <function <lambda> at ...> <map object at ...> [1, 4, 9, 16, 25]
while True:
try:
d3 = c3.__next__()
print(d3)
except StopIteration as e:
break
内置高阶函数 reduce
reduce(function, sequence[, initial]) -> value
需要进行导入 from functools import reduce
将两个参数的 function 从左至右积累(聚合处理)地应用到 iterable 的条目, 以便将该可迭代对象缩减为单一的值
文档
from functools import reduce
# 累加计算
a4 = lambda a, b: a + b
b4 = reduce(a4, c1)
print(c1, a4, b4) # [1, 2, 3, 4, 5, 6, 7] <function <lambda> at ...> 28
# 可以有第三个参数初始值
# 如果有就初始值, 初始值与序列第一个值 放入函数内并计算 计算后的结果是 d4
# 再 d4与序列第二个值 放入函数内并计算 计算后的结果是 新的d4
# ...
# 如果没有初始值, 序列第一个值与序列第二个值 放入函数内并计算 计算后的结果是 d4
# ...
# 求最大值和最小值
a5 = [4, 0, 3, 5, 9, 2, 1, 6, 8, 7]
b5 = lambda a, b: a if a >= b else b
d5 = lambda a, b: a if a <= b else b
c5 = reduce(b5, a5) # 最大
e5 = reduce(d5, a5) # 最小
print(a5, b5, c5, e5) # [4, 0, 3, 5, 9, 2, 1, 6, 8, 7] <function <lambda> at ...> 9 0
内置高阶函数 filter
filter(function or None, iterable) –> filter object
文档
# 保留大于18岁的雇员
employeeItems = [ # employee 雇员
{'name': '张三', 'age': 18, 'salary': 3000}, # salary 工资
{'name': '李四', 'age': 28, 'salary': 1000},
{'name': '王五', 'age': 28, 'salary': 3000},
]
a6 = lambda _: _.get('age') > 18
b6 = filter(a6, employeeItems)
print(employeeItems)
print(a6, b6, list(b6)) # <function <lambda> at ...> <filter object at ...> [{..李四}, {..王五}]
内置高阶函数 min max
min(__iterable: Iterable[_T1], *, key: (_T1) -> SupportsLessThan, default: _T2) -> _T1 | _T2
print('-' * 80)
# 工资大小
a7 = lambda _: _.get('salary') # 通过匿名函数返回需要进行排序的值
b7 = min(employeeItems, key=a7)
c7 = max(employeeItems, key=a7)
print(a7, b7, c7) # <function <lambda> at ...> {'name': '李四', ...} {'name': '张三', ...}
内置高阶函数 sorted
# 排序
# 根据员工年龄降序 reverse=True
a8 = lambda _: _.get('age')
b8 = sorted(employeeItems, key=a8, reverse=True)
# [{'name': '李四', 'age': 28, ...}, {'name': '王五', 'age': 28, ...}, {'name': '张三', 'age': 18, ...]
print(a8, b8) # <function <lambda> at ...>
返回函数
例子1 累加
def a9(*args):
# 居然可以函数内定义函数??
def a10():
s = 0
for _ in args:
s += _
return s
return a10
b9 = a9(1, 2, 3, 4, 5, 6, 7, 8, 9)
print(a9, b9, b9()) # <function a9 at ...> <function a9.<locals>.a10 at ...> 45
例子2 求100以内的质数 (需要时间去理解)
# 的到所有的质数 少于 100的
# 最少质数 2
# 只能被1和本身整除的数
# 偶数(2,0) 全都不是质数过滤一半了
# 只有奇数是可能的
# 的到所有大于1的奇数 生成器
def odd(): # 的到所有大于1的奇数
i = 1
while True:
i += 2
yield i # 大于1的奇数
a11 = odd()
# print(a11) # <generator object odd at ...>
# print(a11.__next__()) # 3
# print(a11.__next__()) # 5
# print(a11.__next__()) # 7
# 整除的函数
# 假设 x是数字9 n就 2,3, 5, 7
def b11(n):
return lambda x: x % n > 0 # x是某个奇数 n小于当前x的一个质数 | >0 表示不能整除
# 质数的生产器
def c11():
yield 2
d11 = odd()
while True:
e11 = next(d11) # 从生成器拿到一个奇数
d11 = filter(b11(e11), d11) # 过滤后再赋值
yield e11
for _ in c11():
if _ < 100:
print(_)
else:
break
# 能理解吗??