文章目录
高阶函数
一、函数就是变量
- python中定义函数就是定义类型是function的变量
- 函数名就是变量名
a = 10
b = lambda x: x*3
c = {'i': 1, 'j': 2}
print(type(a), type(b), type(c)) # <class 'int'> <class 'function'> <class 'dict'>
1.1 一个变量可以给另一个变量赋值
- 加()是调用,不加()是变量名
def func1():
print('我是一个函数。')
z = func1
z() # 我是一个函数。
1.2 修改变量的值
- 变量可以重新赋值
func1 = 100
print(func1) # 100
1.3 变量作为序列的元素
def func2():
return '嘿嘿'
list1 = [func1, func2, func2()]
print(list1[0]) # 100
print(list1[1]) # <function func2 at 0x00000287C9D6A318>
print(list1[2]) # 嘿嘿
1.4 变量作为函数的参数
- 实参高阶函数
def func3(f):
return f , '什么'
print(func3(func2))
print(func3(func2()))
1.5 变量作为函数的返回值
- 返回值高阶函数
- 一个函数的返回值是个函数
def func4():
def g():
print('我是小函数')
return g
func4()() # 我是小函数 - 相当于调用g()
# 面试题
# 定义函数时不执行函数体,所以i 保持原样
# for 循环中的i 在函数外,是全局变量,循环结束时,i 值为4
list2 = []
for i in range(5):
list2.append(lambda x: x*i)
print(list2[1](2)) # 8
print(list2[2](2)) # 8
二、实参高阶函数
2.1 定义
- 参数是函数的函数就是实参高阶函数
def func1(x):
return x()
def func2():
print('helloo')
func1(func2) # func1 就是实参高阶函数
2.2 系统常见实参高阶函数
- max
- min
- sorted
- map
- reduce
2.2.1 max、min
- max(序列) - 比较元素的大小来获取值最大的元素
- max(序列, key=函数) - 函数决定求最大值时候的比较对象
- 是个函数
- 这个函数有且只有一个参数(这个参数指向序列中的元素)
- 有一个返回值(比较对象)
nums1 = [23, 23, 345, 456, 2, 34, 7, 8, 786, 56, 345]
students = [
{'name': '小明', 'age': 23, 'score': 89},
{'name': '小红', 'age': 20, 'score': 96},
{'name': '小张', 'age': 21, 'score': 90}
]
# 列表中最大的元素
print(max(nums1)) # 768
# 分数最高的学生
# print(max(students)) # TypeError: '>' not supported between instances of 'dict' and 'dict'
# 求列表中个位数最大的元素
print(max(nums1, key=lambda x: x % 10)) # 8
# 分数最高的学生
print(max(students, key=lambda x: x['score'])) # {'name': '小红', 'age': 20, 'score': 96}
# 年龄最小的学生
print(min(students, key=lambda x: x['age'])) # {'name': '小红', 'age': 20, 'score': 96}
# 练习:
# 取各位之和最大的元素
nums2 = [23, 78, 90, 73, 233, 91]
print(max(nums2, key=lambda x: sum([int(n) for n in str(x)])))
2.2.2 sorted
- sorted(序列) - 比较序列中元素的大小对序列中的元素从小到大排序
- sorted(序列,key=函数) - 函数决定排序的比较方法
- 函数
- 一个参数,指向序列的元素
- 一个返回值,即为比较对象
print(nums2) # [23, 78, 90, 73, 233, 91]
print(sorted(nums2)) # [23, 73, 78, 90, 91, 233]
# 按个位数从小排
print(sorted(nums2, key=lambda x: x % 10)) # [90, 91, 23, 73, 233, 78]
# 按学生年龄从小排
students = [
{'name': '小明', 'age': 23, 'score': 89},
{'name': '小红', 'age': 20, 'score': 96},
{'name': '小张', 'age': 21, 'score': 90}
]
print(sorted(students, key=lambda x: x['age']))
'''
[{'name': '小红', 'age': 20, 'score': 96},
{'name': '小张', 'age': 21, 'score': 90},
{'name': '小明', 'age': 23, 'score': 89}]
'''
2.2.3 map
- map(函数,序列) - 将序列按指定方式进行转换
- 原序列 -> 新序列
- 有一个参数,指向序列中的元素
- 一个返回值,作为新序列中元素
nums2 = [23, 78, 90, 73, 233, 91]
print(list(map(lambda x: x*2, nums2))) # [46, 156, 180, 146, 466, 182]
-
map跟推导式有什么区别?由于可以自定义函数来用,所以比列表推导式灵活,推导式只能一条语句
-
原序列可以有多个
-
map(函数,序列1,序列2)
- 两个参数,分别指向两个序列中的元素,元素个数一致
- 一个返回值,是新序列中的元素
names = ['张三', '李四', '小明', '小红']
ages = [13, 14, 16, 14]
print(list
(map(lambda x1, x2:
{'name': x1, 'age': x2},
names, ages)))
'''
[{'name': '张三', 'age': 13},
{'name': '李四', 'age': 14},
{'name': '小明', 'age': 16},
{'name': '小红', 'age': 14}]
'''
# 班级总成绩
chinese = [90, 89, 88, 99, 27, 76, 56]
english = [98, 78, 66, 82, 90, 12, 78]
math = [23, 98, 100, 72, 69, 27, 96]
stu_totall = map(lambda c, e, m: c+e+m, chinese, english, math)
print(list(stu_totall)) # [211, 265, 254, 253, 186, 115, 230]
2.2.4 reduce
from functools import reduce
- reduce(函数,序列,初始值)
-
两个参数
- 第一个 - 第一次指向初始值;第二次开始指向上一次的运算结果
如果没有初始值,第一个默认是序列的第一个元素 - 第二个 - 指向序列中的每个元素
- 第一个 - 第一次指向初始值;第二次开始指向上一次的运算结果
-
一个返回值,决定运算规则
-
nums2 = [23, 78, 90, 73, 233, 91]
print(reduce(lambda x, item: x+item, nums2, 0)) # 588
- 函数会被不断调用
# 将数字拼接在一起
print(reduce(lambda heap, item: heap+str(item), nums2, '')) # 2378907323391
三、无参装饰器
3.1 什么是装饰器
- 作用:用来给函数添加功能
- 本质:也是个函数;实参高阶函数+返回值高阶函数+糖语法
- 用法:输入原函数,输出改造后的新函数
def 函数名1(参数1):
def 函数名2(*args, **kwargs):
新增功能的代码
原函数的返回值 = 调用原函数的代码 参数1(*args, **kwargs)
return 原函数的返回值
return 函数名2
import time
def count_time(fn):
def new_fn(*args, **kwargs):
start = time.time()
result = fn(*args, **kwargs)
end = time.time()
print(end - start)
return result
return new_fn
3.2 使用装饰器
- 在被装饰的函数定义上一行加上 @装饰器名
@count_time
def func1():
print('函数1的功能')
@count_time
def func2(x, y):
print(x+y)
func1()
func2(1, 2)
# 练习:用装饰器,在函数开始打印‘start!‘,
def report_start(fn):
def new_fn(*args, **kwargs):
print('start!')
result = fn(*args, **kwargs)
return result
return new_fn
@report_start
def say_hello():
print('hello world!')
say_hello()
- 糖语法本质
fn = 装饰器(fn)