Python中的没有“三器”这一说法,只是可以总结为,三器是指:装饰器,迭代器,生成器。一闭是指闭合器。
闭包
高阶函数+嵌套就可以构成一个基本的闭包。
闭包满足条件:
- 嵌套函数;
- 内层函数引用外层函数的变量;
- 内层函数返回内层函数的地址。
def f1(x):
b=3
def f2():
print(b+x)
return f2
res=f1(10)
print(f1(10))
res()
输出结果:
由以上结果看出,f1(10)得到的返回值是一个f2函数的地址<function f1..f2 at 0x00000219F707BA60>,并且将f2的函数地址返回给f1,所以f1得到的是一个新的函数地址。
# 可变类型
def fun(): #普通函数
l1 = []
l1.append(11)
print(l1)
def fun1(): #闭包函数
l2 = []
def fun2():
l2.append(11)
print(l2)
return fun2
# 普通函数
fun()
fun()
res1=fun1()
res1()
res1()
输出结果:
由以上结果就可以看出普通函数和闭包函数的区别,普通函数在调用一次之后,不会保存结果,所以每次只会返回一次运行结果。而闭包函数的外层的变量是保存下来了的,调用多少次,就会保存多少次运行结果在里面。
装饰器
装饰器是闭包的一种实现方式
装饰器的作用:在不改变原有函数调用方式的基础上,增加新的功能
@装饰器
定义装饰器:
# 定义装饰器
def zs(f):
def inner():
#使用外层函数的变量
print('大家好,我叫XXX')
f() #f函数地址,f()使用函数
return inner #返回内层函数的地址
@zs
def say_hello():
print('你好')
say_hello()
say_hello()
输出结果:
由以上结果看出调用装饰函数之后,每执行一次函数,装饰函数都会跟着运行一次,但并不会改变原有函数的功能,只是在原有功能之上新增一些功能。
l11 = []
def zx_cx(f): #接收add_std1函数地址
def inner1():
f() #调用接收到的函数地址
if 'XX' in l11:
print('已经存在')
else:
print('meiyou')
return inner1
@zx_cx
def add_std1():
name = 'XX'
l11.append(name)
print(l11)
print(add_std1)
add_std1()
输出:
上述执行过程分析:先执行11行:执行装饰函数器函数,把下方的add_std1的函数名以参数形式传递给zx_cx,早zx_cx中,f接收到了add_atd1的函数地址,zx_cx把内能函数inner1的地址返回给了add_atd1。12行在内存中定义了add_std1函数名,add_atd1指向的是inner1的地址,18行执行的是inner1函数,在inner1里面执行f(),f保存的是add_std1,实际是在执行12行的add_std1(),add_atd1执行完回到第三行,inner1执行完回到第18行。
迭代、可迭代对象、迭代器、生成器
迭代:从容器的第一个元素开始,到最后一个元素
可迭代对象:允许被迭代的对象(可理解为一个容器)
迭代器:访问容器元素的一个对象(访问数据,自己本身没数据)
生成器:特殊的迭代器,可自己创建数据和访问数据
from collections.abc import Iterator,Iterable
# 迭代器:Iterator
# 可迭代对象:Iterable
list = [23]
print(isinstance(list,Iterator))
print(isinstance(list,Iterable))
输出:
dir()
dir()查看变量具有的方式属性
list = [23]
print(dir(list))
print(isinstance(list,Iterable))
print(isinstance(list,Iterator))
输出:
当看见输出结果中由iter(),说明该变量是可迭代对象
res = map(lambda x:x**2,[2,3,4,5])
print(isinstance(res,Iterable))
print(isinstance(res,Iterator))
print(dir(res))
输出结果:
发现res变量不仅是可迭代对象,同时也是迭代器,因为输出结果中含有next()
注意: 可迭代对象不一定是迭代器,但迭代器一定是可迭代对象。
list = [23]
list1 = iter(list) #iter()拿到可迭代对象的迭代器
print(isinstance(list1,Iterator))
print(isinstance(list1,Iterable))
输出代码:
生成器
生成器通过**next()**取值
生成器:一般边生成边计算
#第一种方法
g1 = (i for i in range(10)) #生成器,里面没有数据,可以省内存
print(g1,type(g1))
l1 = [i for i in range(10)]
for i in l1:
print(i)
输出结果:
#第二种方法 生成器函数,用yield返回值
#return即是返回值的意思,也是结束代码执行的意思
def g2():
yield 1
def g3():
return 1
print(g2())
print(g3())
输出代码:
#第二种方法 生成器函数,用yield返回值
#return即是返回值的意思,也是结束代码执行的意思
def g2():
yield 1
yield 2
yield 3
yield 4
print(g2()) #拿到返回值,返回g2地址
res=g2()
print(next(res))
print(next(res))
print(next(res))
for i in res:
print(i)
输出结果: