11 Python学习之迭代器和生成器
迭代器和生成器
迭代器
可迭代对象:
当一个对象能够一次返回一个成员,我们称这个对象为可迭代对象,常见的可迭代对象有:
-
顺序结构的有:str、list、tupe
-
无需结构的有:dict、set
-
类的对象拥有
__iter__
和__getitem__
方法
迭代器
当一个可迭代的对象,作为参数传递给内置函数 iter() ,就会返回一个迭代器对象
迭代器中必须包含__next__
方法和__iter__
方法
判断一个对象是不是迭代器:__next__
方法和__iter__
方法在不在dir(对象名)中,dir返回的是一个列表,如果这两个方法在这个列表中,那么该对象就是一个迭代器
注意:
如果读取数量超出了迭代器内的成员数量,会报StopIteration
错误;
例:
用while循环实现for循环效果:
li = [1, 2, 3, 4, 5] # 可迭代对象--列表
obj = iter(li) # 可迭代对象传入iter函数,生成迭代器并赋值给obj
while True:
try:
print(next(obj)) # 循环取出迭代器中的值
except StopIteration: # 取到最后一个会报错,捕获异常,并退出循环
break
将可迭代对象转换成迭代器
语法:
iter(可迭代对象)
例1:
li = list(range(10))
ret = iter(li)
print(ret)
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())
print(next(ret))
运行结果:
<list_iterator object at 0x7fea39ddf470>
0
1
2
3
可迭代对象和迭代器对比
可迭代对象 | 迭代器 |
占内存空间大(几百万的数据8G内存都能承受) | 占内存小 |
速度快 | 速度慢 |
可返回 | 不可返回 |
可直观看到数据 | 数据不可见 |
生成器
在python社区,生成器与迭代器被看成是同一种,生成器的本质就是迭代器。唯一的区别:生成器是我们自己用Python代码构建的数据结构,迭代器是系统提供或转化得来的。
获取生成器的三种方式:
- 生成器函数
- 生成器表达式
- python内部提供的一些
yield
只要在函数中出现了yield,那么他就不是一个函数了,而是一个生成器
例1:
# 函数
def func(a, b):
return a + b
ret = func(3, 5)
print(ret) # 直接返回计算的结果 8
# 生成器
def func(a, b):
yield a + b
ret = func(3, 5)
print(ret) # 返回的是一个生成器,需要用next获取返回值
print(next(ret)) # 值是 8
例2:
生产汽车,按迭代对象的方式,就是一开始就全部生产出来,所用时间和内存都很大
用生成器,需要多少生产多少,所占内存和使用时间少
# 迭代对象方式
def get_func():
li = []
for i in range(50001):
li.append(f"{i}号汽车")
return li
ret = get_func()
print(ret) # 一次创建5万个
# 生成器方式
def get_func():
for i in range(50001):
yield f"{i}号汽车"
ret = get_func() # 此时,并不会创建,next调用时才创建
# 生产200辆
for _ in range(201): # 创建200个
print(next(ret))
# 再生产100辆
for _ in range(100): # 创建100个
print(next(ret))
yield from
yield from返回列表的每一个元素,相当于用了for循环用yield取出
例1:
def get_func():
li = [1, 2, 3, 4, 5]
yield from li # 相当于 for i in li: yield i
ret = get_func()
print(next(ret))
print(next(ret))
print(next(ret))
print("执行了三次")
print(next(ret))
运行结果:
1
2
3
执行了三次
4
例2:
def get_func():
li = [1, 2, 3, 4, 5]
li2 = ['卫龙', '馒头', '花卷', '包子', '油条']
yield from li
yield from li2
ret = get_func()
for i in range(10):
print(next(ret), end=' ')
运行结果:
1 2 3 4 5 卫龙 馒头 花卷 包子 油条
yield和return的区别
yield | return |
可以存在多个yield,取值时一个next对应一个yield | 只能存在一个,遇到return函数就结束了 |
需要用迭代器获取返回的结果 | 直接返回结果 |
例1:
def func(a, b):
yield a + b
yield '返回a+b的结果'
yield '结束'
ret = func(3, 5)
print(next(ret))
print(next(ret))
print(next(ret))
结果是:
8
返回a+b的结果
结束