1.高阶函数(闭包)
- 接收函数作为参数,或者将函数作为返回值的函数都是高阶函数
# 定义一个函数,将列表中所有的偶数,保存到一个新的列表返回
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def fn(lst):
# 创建一个新的列表
new_lst = []
# 对列表进行遍历
for i in lst:
# 判断奇偶
# if not i & 1:
if i % 2 ==0:
new_lst.append(i)
return new_lst
上述的代码将判断奇偶的函数直接嵌套进了fn函数中,若要输出大于5的数时,就需要对fn函数再进行修改,不太方便。因此可以采用高阶函数,如下:
# fn2()函数是判断偶数的函数
def fn2(n):
if n % 2 == 0:
return True
# fn3()函数是判断大于5的数的函数
def fn3(n):
if n >5:
return True
else:
return False
# 该函数即为高阶函数(参数一:作为返回值的函数对象 参数二)
def fn(func,lst):
# 创建一个新的列表
new_lst = []
# 对列表进行遍历
for i in lst:
if func(i):
new_lst.append(i)
return new_lst
print(fn(fn2,lst)) # 注意这里应该用fn2,而不是fn2(),因为需要传入的是对象,而非调用该函数
2. 闭包
- 将函数作为返回值也是高阶函数我们也称为闭包
- • 闭包的好处
• 通过闭包可以创建一些只有当前函数能访问的变量
• 可以将一些私有数据藏到闭包中 - 行成闭包的条件
• 函数嵌套
• 将内部函数作为返回值返回
• 内部函数必须要使用到外部函数的变量
例1:
def fn():
a = 123
# 函数内部定义了一个函数
def fn1():
print('我是fn1...',a)
# 将函数fn1作为返回值返回
return fn1
# r这个函数总是能访问fn()内部的变量
r = fn() # r接收的是fn的返回值:fn1这个对象,即r=fn1
r() # 相当于执行fn1()函数,打印 我是fn1...',123
print(r) # <function fn.<locals>.fn1 at 0x0000022D26392950>
print(a) # 访问不到a
print(fn()) # 返回的是函数对象fn1 <function fn.<locals>.fn1 at 0x0000022D263929D8>
例2:定义一个函数 求平均值
# 定义一个函数 求平均值
nums = []
def average(n):
# 将n添加到列表当中
nums.append(n)
return sum(nums) / len(nums)
print(average(10)) # 10.0
print(average(30)) # 20.0
print(average(10)) # 16.666666666666668
# 若是中间将nums清空,会影响平均值
print(average(10))
print(average(30))
nums = [] # 这个会影响下面的值,会清空nums的值
print(average(10)) # 10.0
面对上面那种影响情况,可以采用闭包来解决
# 但是下面的闭包方法,nums=[]就不会影响后面的值
def make_average():
nums = []
def average(n): # 函数嵌套
# 将n添加到列表当中
nums.append(n) # 内部函数用到了外部函数的变量nums
return sum(nums)/len(nums)
return average # 将内部函数作为返回值
average = make_average()
print(average(10)) # 10
nums = [] # 即不会清空,不起作用,不会影响函数内部的nums
print(average(30)) # 20
3.匿名函数
- 1.filter() 可以从序列中过滤出符合条件的元素,保存到一个新的序列中
- 参数一 函数 根据该函数来过滤序列
- 参数二 需要过滤的序列
- 返回值 过滤后的新序列
例3:filter 过滤函数 求3的倍数
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 3的倍数
def fn3(n):
if n % 3 == 0:
return True
return False
print(list(filter(fn3,lst))) # [3, 6, 9]
print(filter(fn3,lst)) # <filter object at 0x00000243A7101BE0>
- 2.lambda 函数:该函数表达式专门用来创建一些 简单的 函数,它是函数的另一种创建方式
- 语法: lambda 参数列表 : 返回值
例4:lambda 函数 一个简单函数:求两数之和
def fn5(a,b):
return a+b
# fn5()函数与下面的lambda函数等价
(lambda a,b : a + b)(1,2) # 匿名函数,不需要重新定义一个函数,大材小用
print(fn5(1,2)) # 3
print((lambda a,b : a + b)(1,2)) # 3
4.装饰器的引入与使用
4.1 装饰器的引入
- 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
- 如果修改的函数多,修改起来会比较麻烦
- 不方便后期的维护
- 这样做会违反开闭原则(ocp):程序的设计,要求开发对程序的扩展,要关闭对程序的修改
# 求和函数
def add(a,b):
r = a + b
return r
# 求乘积函数
def mul(a,b):
return a * b
# 我们希望在不修改原函数的情况下,对函数进行扩展
# 可以定义一个新的函数,来对函数进行扩展
# 对加法进行扩展
def new_add(a,b):
print('函数开始执行....')
r = add(a,b)
print('函数执行结束....')
return r
q = new_add(1,2)
print(q)
# 结果 :
# 函数开始执行....
# 函数执行结束....
# 3
# 对乘法进行扩展
def new_mul(a,b):
print('函数开始执行....')
r = mul(a,b)
print('函数执行结束....')
return r
q = new_mul(1,2)
print(q)
# 结果 :
# 函数开始执行....
# 函数执行结束....
# 2
4.2 装饰器的使用
- 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
- 在开发中,我们都是通过装饰器来扩展函数的功能的
def start_end(old):
# 用来对其他的函数进行扩展,是其他的函数可以在执行前打印开始执行,执行结束后打印执行结束
# 创建一个新的函数
def new_function(*args,**kwargs):
print('开始执行....')
# 调用被扩展的函数
result = old(*args,**kwargs)
print('执行结束。。。')
return result
return new_function
f = start_end(add) # f接收的是函数对象new_function
r = f(1,2) # r接收的是 result
print(f) # <function start_end.<locals>.new_function at 0x0000024F223A29D8>
print(r) # 3
# 例如像 start_end() 这一类函数我们称之为装饰器
# 通过装饰器,可以在不修改原来函数的情况下,来对函数进行扩展
# 在开发中,我们都是通过装饰器来扩展函数的功能
def fn():
print('我是fn函数')
f = start_end(fn)
r = f()
# 结果:
# 开始执行....
# 我是fn函数
# 执行结束。。。
print(f) # <function start_end.<locals>.new_function at 0x0000022B7FAB29D8>
print(r) # None