迭代器
什么是迭代器
迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的,单纯的重复并不是迭代。
为何要有迭代器
迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型有: 列表,字符串,元组,字典,集合,打开文件
文件是可迭代对象,也是迭代器
with open("关于成长.txt", "wt", encoding="utf-8") as file_obj:
file_obj.write("你懂的越多,你就越像这个世界的孤儿。")
with open("关于成长.txt", "rt", encoding="utf-8") as file:
file_iter = file.__iter__() # file_iter = iter(file)
print(file_iter.__next__())
print(file_iter.__next__())
Traceback (most recent call last):
File "E:\xxx.py", line 13, in <module>
print(file_iter.__next__())
StopIteration
hero_list = ["小满", "大乔", "王昭君"]
index = 0
while index < len(hero_list):
print(hero_list[index])
index += 1
小满
大乔
王昭君
上述迭代取值的方式只适用于有索引的数据类型:列表、字符串、元组
为了解决基于迭代器取值的局限性 python必须提供一种能够不依赖于索引的取值方式,这就是迭代器
如何使用迭代器
什么是可迭代对象
但凡内置有
__iter__
方法的,都称之为可迭代对象
可迭代对象(iterable
)指的是可以依次返回其内部成员的对象。比如字符串、列表、字典、文件等都是可迭代对象。从语法方面说就是那些具有__iter__
的方法的对象,对于类来说指的是那些具有__getitem__
方法的对象。
s1 = '' # 字符串
s1.__iter__()
l = [] # 列表
l.__iter__()
t = (1,) # 元组
t.__iter__()
d = {'name': '小满'} # 字典
d.__iter__()
set1 = {1, 2, 3} # 集合
set1.__iter__()
with open('迭代对象.txt', mode='w', encoding='utf-8') as f: # 文件
f.__iter__()
f.__next__()
如何使用迭代器
调用可迭代对象下的
__iter__
方法,会将其转成迭代器对象
dic = {"a": 1, "b": 2, "c": 3}
dic_iterator = dic.__iter__() # 相当于iter(dic)
print(dic_iterator.__next__()) # 相当于next(dic_iterator)
print(dic_iterator.__next__())
print(dic_iterator.__next__())
print(dic_iterator.__next__())
a
b
c
Traceback (most recent call last):
File "E:\xxx.py", line 12, in <module>
print(dic_iterator.__next__())
StopIteration
在一个迭代器取值干净的情况下,再对其取值取不到。
dic = {"a": 1, "b": 2, "c": 3}
items = dic.__iter__()
while True:
try:
print(items.__next__())
except StopIteration:
break
print("==========>")
while True:
try:
print(items.__next__()) # 取不到了
except StopIteration:
break
a
b
c
==========>
如果想再取一次怎么办?重新赋值一次
dic = {"a": 1, "b": 2, "c": 3}
items = dic.__iter__()
while True:
try:
print(items.__next__())
except StopIteration:
break
print("==========>")
items = dic.__iter__()
while True:
try:
print(items.__next__()) # 取不到了
except StopIteration:
break
a
b
c
==========>
a
b
c
可迭代对象与迭代器对象详解
可迭代对象可以转成成迭代器对象
:内置有__iter__
方法的对象。
可迭代对象.__iter__()得到迭代器对象
迭代器对象:内置有__iter__
方法并且内置有__next__
方法的对象
迭代器对象.__next__():得到迭代器的下一个值
迭代器对象.__iter__():得到迭代器本身,说白了调了跟没调一样
看案例
dic = {"a": 1, "b": 2, "c": 3}
items = dic.__iter__()
print(items is items.__iter__().__iter__().__iter__().__iter__())
True
迭代器优缺点
优点:
为序列和非序列类型提供了一种统一的迭代取值方式;
惰性取值;每次只取一个数据,不占内存;迭代器保存的是产生数据的算法,而不是实际的数据。
缺点:
除非取尽,否则无法获取迭代器的长度;
只能往后依次取值,不能返回头往前取值。就像象棋中的卒,只进不退。
for循环的工作原理
for循环可以称之为迭代器循环
dic.__iter__()
得到一个迭代器对象- 迭代器对象
.__next__()
拿到一个返回值,然后将该返回值赋值给for index in ...
中的index
- 循环往复步骤2,直到抛出异常
StopIteration
异常for循环会捕捉异常然后结束循环
list("hello")
原理同for循环
生成器
如何自定义生成器:
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会返回一个生成器对象,生成器即自定义的迭代器。 如果取完了一样会报
StopIteration
错误
def func():
print("第1次")
yield 1
print("第2次")
yield 2
print("第3次")
yield 3
print("第4次")
g = func()
# 会触发函数体代码的运行,遇到yield停下来,将yield后面的值当做本次调用后的返回结果
res = g.__next__() # next(g)
print(res)
res2 = g.__next__()
print(res2)
res3 = g.__next__()
print(res3)
res4 = g.__next__()
print(res4)
第1次
1
第2次
2
第3次
3
第4次
报错 StopIteration
应用案例
def my_range(start, stop, step=1):
print("start...")
while start < stop:
yield start
start += step
print("end...")
res = my_range(1, 5, 2)
print(next(res)) # res.__next__()
print(next(res)) # res.__next__()
print(next(res)) # res.__next__()
start...
1
3
end...
报错:StopIteration
def my_range(start, stop, step=1):
print("start...")
while start < stop:
yield start
start += step
print("end...")
for index in my_range(1, 9, 2):
print(index)
start...
1
3
5
7
end...
yield的表达形式
def hero(name):
print(f"{name}准备吃东西啦...")
while True:
# food拿到的就是yield接收的值
food = yield
print(f"{name}吃了{food}")
g = hero("小满")
g.send(None) # 等同于 next(g)
g.send("红buff")
g.send("蓝buff")
g.close() # 关闭后无法传值
g.send("红buff")
小满准备吃东西啦...
小满吃了红buff
小满吃了蓝buff
报错:StopIteration
标签:__,.__,迭代,生成器,iter,next,print
From: https://www.cnblogs.com/ccsvip/p/17896860.html