--coding:utf-8--
Author : 妙玄
File :iterator.py
1. 什么是迭代器:
迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的,单纯的重复不是迭代
例如:
count = 0
while count<10:
print(count)
count += 1
2.为什么要有迭代器
对于字符串,列表,元组这种有索引的数据类型,可以按照索引进行迭代取值,但是对于字典,集合,文件这种没有索引的数据类型是不能
按照索引进行迭代取值的,所以python必须提供一种不依赖于索引的取值方式,这就是迭代器。
3.如何使用迭代器
可迭代对象:但凡有内置__iter__方法的都可称之为迭代器
str = ""
str.__iter__()
lis = []
lis.__iter__()
tup = (1,)
tup.__iter__()
dic = {'a':1}
dic.__iter__()
set1 = {1,2,3}
set1.__iter__()
with open("a.txt",mode='rt') as file :
file.__iter__()
调用可迭代对象下的__iter__方法会将其转换成一个迭代器对象
在一个迭代器取值取完的情况下,再取值时取不到
dic_iterator = {'a':1,'b':2,'c':3,'d':4}
result = dic_iterator.__iter__()
while True:
try:
print(result.__next__())
except StopIteration:
break
4. 可迭代对象与迭代器对象
可迭代对象:(可以转换成迭代器的对象,内置有__iter__()方法);;可迭代对象.__ietr__()====>迭代器对象
迭代器对象:有__next__()方法,也有__iter__()方法
迭代器对象.__next__()====>得到迭代器的下一个值
迭代器对象.__iter__()====>得到的是迭代器的本身:目的是为了不管是迭代器对象还是可迭代对象都能够采用一种工作机制
dic_iterator = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
result = dic_iterator.__iter__()
print(result is result.__iter__())
5. for循环的工作原理:
(1)对循环对象调用__iter__()方法得到一个迭代器对象
(2)得到的迭代器对象调用其内置方法__next__()拿到一个返回值,将该返回值赋值给 K
(3)循环往复步骤二,直到抛出异常StopIteration,for循环会捕捉异常,结束循环
dic_iterator = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
for k in dic_iterator:
print(k)
因此:for循环可称之为迭代循环
6. 迭代器总结
(1)使用统一的方案
(2)节省内存
(3)取值不如索引方便
(4)有生命周期
(5)惰性计算:只有调用了__next__()方法之后才有值,调用一次在内存中只产生一个值
(6)只能去取下一个值
7. 自定义迭代器(生成器):
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码,会返回一个生成器对象,生成器即自定义的迭代器
def func():
print("第一次执行")
yield 1
print("第二次执行")
yield 2
print("第三次执行")
yield 3
print("第四次执行")
result = func()
# print(result) # 结果是:<generator object func at 0x00000206791EA660>(生成器对象函数)
# result.__next__() # 当调用__next__()方法时,会触发函数的第一次运行,并将yield后面的值当作本次调用的结果返回
print(result.__next__()) # 返回结果是:
第一次执行
1
此时的函数并没有完全结束运行,而是被暂停在第一个yield关键字后面
8. 应用案例:
def my_range(start, stop, step):
print("start=======>")
while start < stop:
yield start
start += step
print("stop========>")
for i in my_range(1, 7, 2):
print(i)
9. yield 表达式
x = yield 返回值
def dog(name):
print(“道哥%s准备吃东西” % name)
while True:
x = yield #==> x 拿到的是send传给yield的值
print(“道哥%s吃了%s” % (name,x))
g = dog(“alex”) # ==>产生一个生成器对象
#next(g) # >触发函数的运行 函数暂停在yield处
g.send(None) #>相当于next(g) ==> x=None
g.send(‘1232’) # ==>send为yield传值赋值给x
g.send(‘1232’)
g.send(‘1232’)
g.send(‘1232’)
g.close() # 关闭之后不能继续传值
10. 综合运用
def dog(name):
food_list = []
print(“道哥%s准备吃东西” % name)
while True:
x = yield food_list #==> x 拿到的是send传给yield的值
print(“道哥%s吃了%s” % (name,x))
food_list.append(x)
g = dog(“alex”) # ==>产生一个生成器对象
res = g.send(None) # 第一次send拿到yield的返回值,程序暂停在yield处
print(res)
当下一次给yield传值的时候,yield先将值传给x,然后运行后面的代码,再然后将重新拿到的返回值返回
res1 = g.send(“sadhjs”)
print(res1)