1 高阶函数
例子 将 lst = [1,2,3,4,5,6,7,8,9,10] 中所有的偶数,保存到一个新的列表中返回
lst = [1,2,3,4,5,6,7,8,9,10]
# 定义一个函数 用来将指定列表中所有的偶数,保存到一个新的列表中返回
def fn(lst):
# 参数 要进行筛选列表
# 创建一个新的列表
new_lst = []
for n in lst:
# 判断n的奇偶
if n % 2 == 0:
new_lst.append(n)
return new_lst
print(fn(lst))
结果
[2, 4, 6, 8, 10]
引出高阶函数
-
满足2个条件任意一个都是高阶函数:
接收一个或多个函数作为参数
将函数作为返回值返回
例子:将 lst = [1,2,3,4,5,6,7,8,9,10] 中所有的奇数,保存到一个新的列表中返回
lst = [1,2,3,4,5,6,7,8,9,10]
# 定义一个函数 用来将指定列表中所有的偶数,保存到一个新的列表中返回
def fn(lst):
# 参数lst 要进行筛选列表
# 定义一个函数 用来测偶数
def fn2(i):
if i % 2 == 0:
return True
# 创建一个新的列表
new_lst = []
for n in lst:
# 添加
if not fn2(n):
new_lst.append(n)
return new_lst
print(fn(lst))
结果
[1, 3, 5, 7, 9]
例子:将 lst = [1,2,3,4,5,6,7,8,9,10] 中大于5的数,保存到一个新的列表中返回
lst = [1,2,3,4,5,6,7,8,9,10]
# 定义一个函数 用来将指定列表中所有的偶数,保存到一个新的列表中返回
def fn(lst):
# 参数lst 要进行筛选列表
# 定义一个函数 用来检测是否大于5
def fn3(i):
if i > 5:
return True
return False
# 创建一个新的列表
new_lst = []
for n in lst:
# 添加
if fn3(n):
new_lst.append(n)
return new_lst
print(fn(lst))
结果
[6, 7, 8, 9, 10]
- 但是上面两个例子,写死了。
- 下面的可以调用不同的函数
- 当我们使用一个函数作为参数时,实际上我们就是将指定的代码传递给了目标函数
lst = [1,2,3,4,5,6,7,8,9,10]
# 定义一个函数 用来测偶数
def fn2(i):
if i % 2 == 0:
return True
# 定义一个函数 用来检测是否大于5
def fn3(i):
if i > 5:
return True
return False
# 定义一个函数 用来检测是否3的倍数
def fn4(i):
if i % 3 == 0:
return True
return False
def fn(func,lst):
# 参数lst 要进行筛选列表
# 创建一个新的列表
new_lst = []
for n in lst:
# 添加
if func(n):
new_lst.append(n)
return new_lst
print(fn(fn4,lst))
调用fn4结果
[3, 6, 9]
2 闭包
# 将函数作为返回值返回,我们也称为闭包
def fn():
# 在函数内部定义一个函数
def fn2():
print('我是fn2')
# 将内部函数作为返回值返回
return fn2 # 返回的是函数对象
print(fn())
结果
<function fn.<locals>.fn2 at 0x000001717CAD5620>
# 将函数作为返回值返回,我们也称为闭包
def fn():
# 在函数内部定义一个函数
def fn2():
print('我是fn2')
# 将内部函数作为返回值返回
return fn2 # 返回的是函数对象
# r是一个函数,是调用fn()后返回的函数,这个函数是在fn内部定义,并不是全局函数
r = fn()
r() # 调用后值是空
print(r())
结果
我是fn2
我是fn2
None
通过闭包可以换创建一些只有当前函数才能访问的对象,还可以将一些私有的数据藏到闭包中
# 将函数作为返回值返回,我们也称为闭包
def fn():
a = 10
# 在函数内部定义一个函数
def fn2():
print('我是fn2',a)
# 将内部函数作为返回值返回
return fn2 # 返回的是函数对象
# r是一个函数,是调用fn()后返回的函数,这个函数是在fn内部定义,并不是全局函数
r = fn() # 值是空 不是全局函数
r()
print(a)
结果
我是fn2 10
NameError: name 'a' is not defined
# # 求多个数的平均值
# nums = [50,20,60,10,80]
#
# # sum() 用来求一个列表中元素之和
# print(sum(nums)/len(nums))
nums = [] # 是全局变量
# 定义一个函数,实现就算平均值
def average(n):
# 将n添加到列表当中
nums.append(n)
# 求平均值
return sum(nums)/len(nums)
print(average(10))
print(average(5))
结果
10.0
7.5
采用闭包的方式
def make_average():
nums = [] # 是局部变量 只能内部看到
# 定义一个函数,实现就算平均值
def average(n):
# 将n添加到列表当中
nums.append(n)
# 求平均值
return sum(nums)/len(nums)
return average
print(make_average())
a = make_average()
print(a(10))
print(a(5))
结果
<function make_average.<locals>.average at 0x000001AA3E100E18>
10.0
7.5
形成闭包的条件:
函数嵌套
将内部函数作为返回值返回
内部函数必须使用到外部函数的变量
当不希望别人去修改的时候,使用闭包
3 装饰器的引入
# 求任意两个数的和
def add(a,b):
print('开始计算')
print('计算结束')
return a + b
# 求任意两个数的乘积
def mul(a,b):
return a * b
r = add(1,20)
print(r)
结果
开始计算
计算结束
21
-
我们可以通过修改函数中的代码来完成装饰,但是会产生一些问题:
修改的函数很多
不方便后期的维护
会违反开闭原则(ocp) 程序设计 要求对程序的扩展,但是要关闭对程序的修改 -
不修改原函数,来对函数进行扩展
# 不修改原函数,来对函数进行扩展
def fn():
print('我是fn函数')
# 定义一个函数 对fn进行扩展
def fn2():
print('函数开始执行')
fn()
print('函数执行结束')
fn2()
结果
函数开始执行
我是fn函数
函数执行结束
# 求任意两个数的和
def add(a,b):
return a + b
# 求任意两个数的乘积
def mul(a,b):
return a * b
r = add(1,20)
def new_add(a,b):
print('函数开始执行')
r = add(a,b)
print('函数执行结束')
return r
result = new_add(1,2)
print(result)
结果
函数开始执行
函数执行结束
3
- 上述较为麻烦
- 因此需要通用的方式了对函数进行扩展
4 装饰器的使用
def fn():
print('我是fn函数')
def add(a,b):
return a + b
def start_end(old): # 类似于start_end(old)就是装饰器
# 用来对其他的函数进行扩展 扩展函数执行的时候打印 开始执行 执行后打印 执行结束
# 参数old---要扩展的函数对象
# 创建一个函数
def new_function(*args,**kwargs): # 参数装包 转换为一个个元组或者字典
# *args用来接收所有的位置参数,,**kwargs用来接收所有的关键字参数
print('开始执行')
# 要调用被扩展的函数
result = old(*args,**kwargs) # 把位置参数拆包,放到元组进去,,或者把关键字 转换字典 传进去
print('执行结束')
return result
# 返回新函数
return new_function
f = start_end(add)
r = f(111,222)
print(r)
结果
开始执行
执行结束
333
- start_end(old) 类似于这样的函数其实就是一个装饰器,通过装饰器可以在不修改原函数的情况下对函数进行扩展,在开发当中,都是通过装饰器来扩展函数的功能
- @
在Python的函数中偶尔会看到函数定义的上一行有@functionName的修饰,当解释器读到@的这样的修饰符之后,会先解析@后的内容,直接就把@下一行的函数或者类作为@后边的函数的参数,然后将返回值赋值给下一行修饰的函数对象。
比如:
@a
@b
def c():
…
python会按照自下而上的顺序把各自的函数结果作为下一个函数(上面的函数)的输入,也就是a(b(c()))
————————————————
版权声明:本文为CSDN博主「saberpan」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/saberpan/article/details/85258781
‘@’引用已有的函数,对下面的函数进行修饰。引用函数必须放在修饰函数的上面,引用函数的返回值,返回给被修饰的函数
https://www.cnblogs.com/liangxiyang/p/11200476.html
例子
def fn():
print('我是fn函数')
def add(a,b):
return a + b
def start_end(old): # 类似于start_end(old)就是装饰器
# 用来对其他的函数进行扩展 扩展函数执行的时候打印 开始执行 执行后打印 执行结束
# 参数old---要扩展的函数对象
# 创建一个函数
def new_function(*args,**kwargs): # 参数装包 转换为一个个元组或者字典
# *args用来接收所有的位置参数,,**kwargs用来接收所有的关键字参数
print('开始执行')
# 要调用被扩展的函数
result = old(*args,**kwargs) # 把位置参数拆包,放到元组进去,,或者把关键字 转换字典 传进去
print('执行结束')
return result
# 返回新函数
return new_function
f = start_end(add)
@start_end
def speak():
print('大家加油')
speak()
结果
开始执行
大家加油
执行结束