1.高阶函数
- 两个条件满足一个即可
- 将函数对象作为返回值返回
- 可以是外部函数也可以是内部函数
- 将一个函数的函数对象作为参数传入一个函数中
- 将函数对象作为返回值返回
#将函数对象作为返回值返回
#外部函数
def fun_inner():
pass
def fun_out():
return fun_inner
f = fun_out()
f()
#内部函数
def fun_out():
def fun_inner():
pass
return fun_inner
f = fun_out()
f()
#将一个函数的函数对象作为参数传入一个函数中
list1 = [1,2,3,4,5,6]
def fun2(n):
if n % 2 == 0:
return True
def fun1(fn):
list2 = []
for i in list1:
if fn(i):
list2.append(i)
return list2
print(fun1(fun2))
2.匿名函数
- 没有名字的函数,不指定函数名字,也成lambda函数
- lambda函数
- 不属于高阶函数
- lambda函数语法:(lamdba 参数:表达式)(传参)
res = (lambda a b:a+b)(1,2)
print(res)
或
res = lambda a b:a+b
print(res(1,2))
- filter()函数
- 高阶函数
- 过滤作用
- 传2个参数
list1 = [1,2,3,4,5,6,7,8,9,10]
def fun(n):
if n % 2 ==0:
return True
print(list(filter(fun,list1)))
3.闭包
- 将函数作为返回值也是⾼阶函数我们也称为闭包
- 闭包的好处
- 通过闭包可以创建⼀些只有当前函数能访问的变量
- 可以将⼀些私有数据藏到闭包中
- ⾏成闭包的条件
- 函数嵌套
- 将内部函数作为返回值返回
- 内部函数必须要使⽤到外部函数的变量
# 闭包的作用: 保存外部函数的变量不被销毁
def fun_out(num1):
# 定义一个内部函数
def fun_inner(num2):
# 内部函数用到了外部函数的变量或参数(num1)
res = num1 + num2
print(res)
print(fun_inner.__closure__)
print(id(num1))
fun_inner(2)
print(id(num1))
return fun_inner
f = fun_out(1)
print(id(fun_out))
f(3)
# 修改外部变量
# def fun_out(num1):
# # 定义一个内部函数
# def fun_inner(num2):
# # 内部函数用到了外部函数的变量或参数(num1)
# # nonlocal num1 # 告诉解释器,此处用的是外部的变量num1 这是闭包的特性
# num1 = 2
# res = num1 + num2
# print(res)
#
# print(num1)
# fun_inner(2)
# print(num1)
#
# return fun_inner
#
#
# f = fun_out(1)
#
# f(3)
# 闭包会保持外部函数变量不被销毁, python内存容易满 慎用
4.装饰器的使用
- 我们可以直接通过修改函数中的代码来完成需求,但是会产⽣以下⼀些问题
- 如果修改的函数多,修改起来会⽐较麻烦
- 不⽅便后期的维护
- 这样做会违反开闭原则(ocp)
- 程序的设计,要求开发对程序的扩展,要关闭对程序的修改
# 装饰器是一个特殊的闭包
# 符合闭包的三大构成条件
# 通用装饰器
def fun_out(fn):
def fun_inner(*args, **kwargs):
print('函数开始执行')
r = fn(*args, **kwargs)
print('函数执行结束')
return r
return fun_inner
# 语法糖: @fun_out 等价于 fun_out(add)
@fun_out # 装饰器语法糖的写法
def add(a, b):
return a + b
r = add(1, 2)
print(r)
5.推导式
- 推导式分为 列表推导式、字典推导式、集合推导式等。⽤的最多列表推导式
- 列表推导式是构建列表(list)的⼀种快捷⽅式,简单理解就是由⼀个旧的列表来构建出⼀个新的列表
- 语法
1 [表达式 for 变量 in 旧列表]
2 [表达式 for 变量 in 旧列表 if 条件]
#列表推导式语法
#[表达式 for 变量 in 旧列表]
list3 = [i for i in range(10)]
print(list3)
# [表达式 for 变量 in 旧列表 if 条件]
list1 = ['cheney', 'jerry', '居然', 'amy']
list2 = [i for i in list1 if len(i) > 3]
print(list2)
6.生成器
-
在⼀定程度上就优化了内存
-
创建⽣成器的⽅式
- 通过列表推导式的⽅式
1 g = (x * 3 for x in range(10))
# 得到从1-100之间得到能整除4的列表 #列表推导式 list1 = [i for i in range(1, 101) if i % 4 == 0] print(list1) #生成器方式 gen = (i for i in range(1, 101) if i % 4 == 0) print(gen, type(gen)) # generator 生成器 #生成器是一个特殊的迭代器, 是一种容器, 数据取完了就没了, 如果没取完,生成器会记住上次取数据的位置,下次你在取得时候,就会从这个位置开始取数据 print(next(gen)) print(next(gen)) print(next(gen)) print(next(gen))
- 通过函数的⽅式
def fu(): n = 0 while True: n += 1 yield n #只要在函数中出现yield关键字它就是⼀个⽣成器函数
# 函数只要有调用,就会进入到函数内部执行程序 没有return打印一个None
# 但是,此时,这个函数已经不是一个函数了,它变成了一个生成器
def fun():
def fun1():
pass
i = 0
while True:
i += 1
yield i # yield和return有同样得返回得效果, yield有阻塞程序得效果
print(i)
r = fun()
# print(r)
print(next(r))
print(next(r))
print(next(r))
7.迭代器
- 关系对应图
- 迭代器是访问集合元素的⼀种⽅式。
- 迭代器是⼀个可以记住遍历位置的对象。
- 迭代器对象从集合的第⼀个元素开始访问,指导所有元素被访问完结束。
- 可以被next()函数调⽤并不断返回下⼀个值的对象称为迭代器Iterator
- ⽣成器是可迭代的,也是迭代器
- 列表是可迭代的,但不是迭代器
- 通过iter()函数可以将可迭代的对象变成⼀个迭代器
- 迭代器可以完成得事情,生成器都可以完成,而且生成器更加得灵活
# 通过不同得可迭代对象可以转换为迭代器,但是对象本质不同
# 可迭代对象 实现了iter()这个方法
# 迭代器对象 实现了 next()、iter()方法
list1 = [1, 2, 3, 4, 5]
tuple1 = (1, 2, 3, 4, 5)
itra = iter(list1)
itra1 = iter(tuple1)
#print(itra) # list_iterator
#print(itra1) # tuple_iterator
list2 = [i for i in itra]
print(list2) #for循环遍历,相当于在容器里取出所有值
print(next(itra)) #因为没有值了,再次取值就会报错StopIteration
# 迭代器可以完成得事情,生成器都可以完成,而且生成器更加得灵活
作业
1.请使用装饰器实现已存在的函数的执行所花费的时间。
• time模块