一、迭代器
定义:拥有 iter 和 next 方法的对象就是迭代器
迭代:是访问集合元素的一种方式,可以将集合元素中的数据’一个挨着一个取出来’叫迭代
(如for循环:–ter-- 方法返回一个迭代器,调用迭代器的–next-- 方法取值)
二、生成器
本质:就是迭代器
两种:生成器函数 与 生成器表达式
1.生成器函数
一个包含yield关键字的函数就是一个生成器函数。并且yield不能和return公用,并且
yield只能用在函数内。
1.生成器函数执行后得到一个生成器作为返回值,并不会执行函数体
2.执行--next--方法后才会执行函数体,并且获得返回值
3.--next--内置方法,内部调用生成器函数的--next--方法
4.yield 与 return 相同的是可以返回值,但yield不会结束函数
def generator():
print('zzz')
yield
res = generator()
print(res) #<generator object generator at 0x000001D29D88D5E8>
res.__next__() #zzz
send() 方法
获取下一个值与next基本一致,只是在获取下一个值时,会给上一个yield的位置传递一个数据
注意事项:
1.第一次使用生成器时,使用next获取下一值
2.最后一个yield不能接受外部的值
2.生成器表达式
格式:与列表推导式类似,将 [ ] 改为 ()即可
egg = ('鸡蛋%s ' % i for i in range(1, 20))
print(egg) #<generator object <genexpr> at 0x000001A742A3D5E8>
print(egg.__next__()) #鸡蛋1
print(next(egg)) #鸡蛋2
回顾列表推导式,并与生成器比较优劣
列表推导式:
lst1 = [i**2 for i in range(1,20) if i % 2 == 0]
print(lst1) #[4, 16, 36, 64, 100, 144, 196, 256, 324]
比较 列表推导式 与 生成器
1.返回数据类型不同
2.生成器所占内存比列表少 (可使用sys.getsizeof()方法查看内存)
from sys import getsizeof
lst2 = [x ** 2 for x in range(2000)]
print(lst2)
a = getsizeof(lst2)
print(a) #16560
gen = (x ** 2 for x in range(2000))
print(gen) #<generator object <genexpr> at 0x000002660A7CD5E8>
print(next(gen)) #0
print(next(gen)) #1
print(next(gen)) #4
b = getsizeof(gen)
print(b) #120
原因:
生成器一次只生成一个,所以它会比列表更有内存效率
如:当迭代列表时,python会保存完整的一个列表,而生成器不会将整个全部元素存储在内存中,并且只会在需要时’生成next/send’序列的下一个元素
三、装饰器
本质:一个闭包函数
作用:在不修改源代码的前提下,对原函数功能进行扩展
格式:@装饰器名
执行原理:先执行距离函数近的装饰器
闭包函数通常3个要求:
1.函数嵌套定义
2.内部函数使用外部函数的变量
3.外部函数返回值为内部函数名
通用闭包:
def fun_out(func):
def func_in(*args,**kwargs):
return func(*args,*kwargs)
return func_in