第十讲:函数三
高阶函数
- 接收函数作为参数,或者将函数作为返回值返回的函数就是⾼阶函数
lst=[1,2,3,4,5,6,7,8,9]
#定义一个函数 可以指定该列表中的所有偶数,保存到一个新的列表
def fn(l):
#l为被指定的列表
#new_list是新创建的列表
new_list=[]
for n in l:
if n%2==0:
new_list.append(n)
return new_list
r=fn(lst)
print(r)
以下为高阶函数
lst=[1,2,3,4,5,6,7,8,9]
#定义一个函数 可以指定该列表中的所有偶数,保存到一个新的列表
def fn(l):
#l为被指定的列表
#new_list是新创建的列表
#在函数中定义一个新函数fn2
def fn2(i):
if i%2==0:
return True
def fn3(i):
if i>5:
return True
return False
new_list=[]
for n in l:
if fn2/3():
new_list.append(n)
return new_list
r=fn(lst)
print(r)
# 当我们使用一个函数作为参数的时候,实际上是将指定的代码传递到了目标函数
lst = [1,2,3,4,5,6,7,8,9,10]
a = 1
# 在函数内部定义一个函数 用来检测一个任意的偶数
def fn2(i):
if i % 2 == 0:
return True
def fn3(i):
if i > 5:
return True
return False
def fn4(i):
if i % 3 == 0:
return True
return False
# 定义一个函数
# 可以指定一个列表中的所有的偶数,保存到一个新的列表
def fn(func,l):
# 参数 l 就是被指定的列表 func
# 创建一个新的列表
new_lst = []
for n in l:
# 判断n的奇偶
if func(n):
new_lst.append(n)
return new_lst
# print(fn(fn2,lst)) # 求偶数
print(fn(fn4,lst)) # 求3的倍数
匿名函数
- filter():一个高阶函数,需要将别的函数作为参数进行传递,可以将我们的可迭代对象进行一个过滤,返回值为可迭代的对象。
lst=[1,2,3,4,5,6,7,8,9]
def fn(n):
if n%3==:
return True
return False
print(filter(fn4,lst))#打印出来是一个对象(尖括号)
print(list(filter(fn4,lst)))#打印出来是列表
- 对于较为简单的问题,没必要自己定义一个单独的函数,可以使用匿名函数来做:
- lambda表达式:专门用来创建一些简单的函数,是函数的另一种创建方式。
- 语法:
lambda 列表参数:返回值
def fn(a,b):
return a+b
print(fn(1,2))#求和函数
print(lambda a,b:a+b)#是一个对象,匿名
print((lambda a,b:a+b)(10,20))
lst=[0,1,2,3,4,5,6,7,8,9]
r=filter(lambda i:i%3==0,lst)
print(r)
- 匿名函数最大的好处是,他只会用一次,用完就会从内存消失
闭包
- 将函数作为返回值也是⾼阶函数的一种,我们也称为闭包
- 闭包的好处
- 可以创建⼀些只有当前函数能访问的变量
- 可以将⼀些私有数据藏到闭包中
- ⾏成闭包的条件
- 函数嵌套
- 将内部函数作为返回值返回
- 内部函数必须要使⽤到外部函数的变量
nums = []
def fn(n):
nums.append(n)
return sum(nums)/len(nums)
print('nums=',fn(10))
nums[20]
print('nums'=fn(20))
#结果为
#nums=10
#nums=20 #第二次对nums的定义覆盖了第一次
def make_fn():
nums = []
def fn(n):
nums.append(n)
return sum(nums)/len(nums)
return fn
mf=make_fn()
print(mf(10))
nums[20]
print(mf(20))
装饰器的引入
- 我们可以直接通过修改函数中的代码来完成需求,但是会产⽣以下⼀些问题
- 如果修改的函数多,修改起来会⽐较麻烦
- 不⽅便后期的维护
- 这样做会违反开闭原则(ocp)
程序的设计,要求开发对程序的扩展,要关闭对程序的修改
原函数
def add(a,b):
c=a+b
return c
r=add(5,6)
print(r)
通过直接修改原函数
def add(a,b):
print('函数开始执行')
c=a+b
print('函数执行结束')
return c
r=add(5,6)
print(r)
通过新建函数对原函数进行修改
def new_add(a,b):
print('函数开始执行')
r = add(a,b)
print('函数执行结束')
return r
r=new_add
print(r)
装饰器的使用
- 通过装饰器,可以在不修改原来函数的情况下来对函数进⾏扩展
- 在开发中,我们都是通过装饰器来扩展函数的功能的
def fn():
print('我是fn函数')
def add(a,b):
r = a + b
return r
# 定义一个函数 就是对其他函数进行扩展的 扩展的功能一个 是打印函数开始执行 一个是打印函数执行结束
def start_end(old):
# 内部创建了一个函数
def new_function(a1,a2):
print('函数开始执行')
r = old(a1,a2)
print('函数执行结束')
# 返回函数的执行结果
return r
# 返回新的函数
return new_function
f=start_end(add)
r=f(1,2)
print(r)
以上函数虽然扩展了原函数,但是随着旧函数的不同,新函数的参数个数需要修改,联想到之前的不定长参数。
def fn():
print('我是fn函数')
def add(a,b):
r = a + b
return r
# 定义一个函数 就是对其他函数进行扩展的 扩展的功能一个 是打印函数开始执行 一个是打印函数执行结束
def start_end(old):
# 内部创建了一个函数
def new_function(*args,**kwargs):#不定长参数
print('函数开始执行')
r = old(*args,**kwargs)
print('函数执行结束')
# 返回函数的执行结果
return r
# 返回新的函数
return new_function
f=start_end(add)
r=f(1,2)
print(r)
可以使用@start_end的方法直接装饰一个函数
#如上定义了装饰器start_end函数
@start_end
def fn3():
print('网抑云上号')
fn3()
#结果直接就是fn3被装饰