迭代器与生成器
目录
迭代器与生成器
一 迭代器 iterator
1 什么是迭代器?(迭代与迭代器)
-器:指的就是工具。
-迭代:是一个重复的过程,但每次重复都是基于上次的结果而来的。
-迭代器:指的是一种不依赖于索引取值的工具。
# 索引取值
names = ['zhangsan','lisi','wangwu']
count = 0
while count < len(names):
print(names[count])
count += 1
2 为何要有迭代器
2.1 迭代器的两个特性
(1) 迭代器是一种不依赖索引取值的工具;
(2) 惰性计算,节省内存。
3 如何使用迭代器
3.1 引入,以字典为例:
dic = {'name':'zhangsan','age':18,'gender':'male'}
dic_iterator = dic.__iter__()
# 一般方法
res1 = dic_iterator.__next__()
print(res1) # 'zhangsan'
res2 = dic_iterator.__next__()
print(res2) # 18
res3 = dic_iterator.__next__()
print(res3) # 'male'
dic_iterator.__next__() # StopIteration
# 使用循环+try语句,可以捕捉异常,使循环及时结束。
while True:
try:
res = dic_iterator.__next__()
print(res)
except StopIteration:
break
3.2 可迭代对象与迭代器对象
3.2.1 可迭代对象
-内置有 __iter__ 方法的数据类型称之为:可迭代对象/类型。 如:字典dictionary、集合set、列表list、字符串string、元组tuple、文件对象file(也是迭代器对象) 。
3.2.2 迭代器对象
-内置有 __next__ 方法与 __iter__ 方法的数据类型称之为:迭代器对象。
dic = {'name':'zhangsan','age':18,'gender':'male'}
dic_iterator1.__iter__()
dic_iterator1.__next__()
print(dic_iterator1.__iter__().__iter__().__iter__() is dic_iterator1) # True
print(dic_iterator2) # <dict_keyiterator object at 0x00000245D0ECD090>
3.2.2.1 为何迭代器对象同时内置了 __next__方法与__iter__方法?
1)-迭代器的创造是为了方便for循环取值,由于for循环取值使用频率很高,所以for k in iterator中,iterator每次都调用 __iter__ 的方法,将可迭代对象直接变为迭代器对象,不进行额外的判断,可以提高效率,所以迭代器对象同时具有了以上两个方法,是为了真正的节省内存。
2)-文件对象由于可能会很大,所以同时具有 __next__ 方法与 __iter__ 方法,以节省内存。
3.2.3 总结:
-迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象。
3.3 for循环的工作原理
dic = {'name':'zhangsan','age':18,'gender':'male'}dic_iterator = dic.__iter__()while True: try: res = dic_iterator.__next__() print(res) except StopIteration: break for k in dic: print(k) """步骤1 先让dic调用__iter__()方法,dic_iterator = dic.__iter__();步骤2 k=dic_iterator.__next__(),执行循环体代码;步骤3 循环往复,直到抛出异常,for循环会帮我们捕捉异常结束循环。"""for k in dic_iterator: # 与上面for k in dic 得出的结果一样 print(k)
3.4 基于同一个迭代器重复取值
# 基于同一个迭代器取值,最终会将迭代器的值取尽,重新开始一个新的迭代取值过程,可以重新制造一个迭代器,再次进行迭代取值。
二 生成器 generator
1 什么是生成器
-但凡是函数内出现了yield关键字,调用函数将不会执行函数体代码,会得到一个返回值,该返回值就是我们自定义的迭代器,称之为生成器。# 生成器的唯一注意事项就是:生成器只能遍历一次。
def func(): print('hello1') yield 111 # 执行到yield会暂停并返回一个值。 print('hello2') yield 222 print('hello3') yield 333g = func()print(g) # 生成器本质就是迭代器 <generator object func at 0x0000025CA029F2E0>res = next(g)print(res) # hello1 # 111res = next(g)print(res) # hello2 # 222res = next(g)print(res) # hello3 # 222next(g) # StopIteration
2 yield与return的异同点
### 1.相同点: 都可以用来返回值。### 2.不同点: return只能返回一次值,函数就会立即结束。 yield可以用于返回多次值,可以挂起函数。
# 案例:使用yield无限取值,每次内存只有一个值。def func(): res=0 while True: res+=1 yield resg=func()for i in g: print(i)
# 实现一个自定义的range功能:def my_range(start, stop, step=1): while stop > start: yield start start += stepfor i in my_range(1,3,1): print(i) # 1 2print(type(my_range)) # <class 'function'>print(type(my_range(1,3,1))) # <class 'generator'>
3 总结迭代器的优点与缺点
### 1.优点: (1) 是一种通用的迭代取值方案; (2) 惰性计算,以节省内存。### 2.缺点: (1) 取值不如索引、key的取值方式灵活; (2) 取值是一次性的,只能往后取,不能预估值的个数。

浙公网安备 33010602011771号