1、高阶函数
1.1 高阶函数的概念
- 接收函数作为参数,或者函数作为返回值的函数就是高阶函数。
1.2 高阶函数的特点
- 特点一 接收一个或多个函数作为参数。
- 特点二 将函数作为返回值。
当我们使用一个函数作为参数的时候,实际上是将指定的代码传递给了目标函数。
'''需求:将一个指定列表中的偶数,保存到一个新的列表中返回'''
lst = [1,2,3,4,5,6,7,8,9,10]
def fn1(i):
if i % 2 == 0:
return True
return False
def fn(f,lst): # 参数lst是要进行筛选的列表
# 创建一个新的列表
new_lst = []
# 对要筛选的列表进行遍历
for n in lst:
# 判断n的奇偶
if f(n):
new_lst.append(n)
# 返回新的列表
return new_lst
print(fn(fn1,lst))
# 运行结果:
# [2, 4, 6, 8, 10]
2、匿名函数
实现需求:将一个指定列表中的能被3整除的数,保存到一个新的列表中返回。可以采用上面高阶函数的方法,如下面的方法一;也可以采用下面的方法二。
'''方法一'''
lst = [1,2,3,4,5,6,7,8,9,10]
def fn1(i):
if i % 3 == 0:
return True
return False
def fn(f,lst): # 参数lst是要进行筛选的列表
# 创建一个新的列表
new_lst = []
# 对要筛选的列表进行遍历
for n in lst:
# 判断n能否被3整除
if f(n):
new_lst.append(n)
# 返回新的列表
return new_lst
print(fn(fn1,lst))
# 运行结果:
# [3, 6, 9]
'''方法二'''
lst = [1,2,3,4,5,6,7,8,9,10]
r = filter(lambda i : i % 3 == 0,lst)
print(list(r))
# 运行结果:
# [3, 6, 9]
2.1 filter()
filter(参数1,参数2)
- 参数1:函数对象
- 参数2:需要过滤的序列(可迭代的对象)
- 返回值:过滤后的新序列(可迭代的对象)
2.2 lambda函数表达式
- 匿名函数 — lambda函数表达式,专门用来创建一些简单的函数。
- 语法:
- lambda 参数列表 : 返回值
lst = [1,2,3,4,5,6,7,8,9,10]
r = filter(lambda i : i % 3 == 0,lst)
print(list(r))
# 相当于
lst = [1,2,3,4,5,6,7,8,9,10]
def fn(i):
return i % 3 == 0
r = filter(fn,lst)
print(list(r))
def fn1(a,b):
return a + b
print(fn1(2,3))
# 运行结果:
# 5
fn2 = lambda a,b : a + b
print(fn2(2,3))
# 运行结果:
# 5
3、闭包
- 通过闭包可以创建一些只有当前函数能够访问的变量,将一些私有数据藏到闭包中。
- 形成闭包的条件:
- 1.函数嵌套
- 2.将内部函数作为返回值返回
- 3.内部函数必须使用到外部函数的变量
# 例1
def fn():
a = 10
# 在函数内部定义一个函数
def fn2():
print('我是fn2',a)
# 将内部函数fn2作为返回值返回
return fn2
r = fn()
r()
# 运行结果:
# 我是fn2 10
# 例2
'''求平均数:在一组数据中所有数据之和再除以这组数据的个数
nums = [1,2,3,4,5,6],这组数的平均数=(1+2+3+4+5+6)/6=3.5'''
def avg_fn():
nums = []
def fn1(n):
nums.append(n)
return sum(nums)/len(nums)
return fn1
m = avg_fn()
print(m(1))
print(m(2))
print(m(3))
print(m(4))
print(m(5))
print(m(6))
# 运行结果:
# 1.0
# 1.5
# 2.0
# 2.5
# 3.0
# 3.5
关于闭包更详细的介绍,参考:https://blog.csdn.net/u013380694/article/details/90019571
4、装饰器
4.1 装饰器的引入
我们可以通过修改函数中的代码来完成需求,但是会产生一些问题:
- 问题一 如果要修改的函数过多,修改起来比较麻烦;
- 问题二 不方便后期的维护;
- 问题三 违反开闭原则(ocp):程序的设计思想,要求开发对程序的扩展,要关闭对程序的修改;
4.2 装饰器的使用
'''定义一个函数来对其他的函数进行扩展,使其他的函数可以在执行前打印“开始执行”,执行后打印“执行结束”'''
def add(a,b):
print('a + b =',a + b)
def start_end(old):
# 创建一个新的函数
def new_function(*args,**kwargs):
print('函数开始执行.....')
r = old(*args,**kwargs)
print('函数执行结束.....')
return r
# 返回函数
return new_function
f = start_end(add)
f(123,456)
# 运行结果:
# 函数开始执行.....
# a + b = 579
# 函数执行结束.....
@start_end
def speak():
print('勇敢地说出自己的想法')
@start_end
def listen():
print('耐心地倾听他人的声音')
speak()
# 运行结果:
# 函数开始执行.....
# 勇敢地说出自己的想法
# 函数执行结束.....
listen()
# 运行结果:
# 函数开始执行.....
# 耐心地倾听他人的声音
# 函数执行结束.....
- 上面的例子中,start_end(old)这一类函数我们就称之为装饰器;
- 通过装饰器(“@start_end”的形式),可以在不修改原来函数的情况下来对函数进行扩展;
- 在开发中,我们都是通过装饰器来扩展函数的功能。
- 语法:@×××