1、迭代器协议:
对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么引起一个Stopiteration异常,以终止迭代。从本质上来说,字符串、列表、元组、字典都不是可迭代对象,因为for循环才变成了可迭代对象,调用的是__iter__()方法。
2、iter()方法:
iter()是把一个对象变成可遍历的,但是无法向下进行,通过__next__()方法 或 next() 方法进行调用。iter(可迭代对象,迭代的终点)。next方法会记住上次的位置,从上次的位置进行next。
list_1 = [1, 2, 3, 45, 6]
# 将list_1变成迭代器
a = iter(list_1)
print(a)
# 打印下一个元素
print(a.__next__())
# 打印下一个元素
print(next(a))
也可以通过重写__next__()方法实现迭代器:重写__next__()方法。
class Test:
def __next__(self):
self.n += 1
if self.n == 13:
raise StopIteration('到头了')
return self.n
def __iter__(self):
return self
def __init__(self, n):
self.n = n
t = Test(10)
print(t.__next__())
print(t.__next__())
print(t.__next__()) # 第三次会报错
3、生成器:
yeild类似return,但是yeild不会立刻退出程序,会挂起(保存上下文),再次调用时从上一个yeild处继续执行。可以有多个yield返回不同的值,返回值但会组成一个列表。
# 此时就不是一个函数,而是一个生成器。
def test():
print("----------")
yield
print("+++++++++")
yield
print("***********")
t = test()
print(t)
print(t.__next__()) # 通过调用进行
print(next(t))
触发生成器的方法1、通过系统内部函数next(object) 2、调用函数__next__() 3、通过send()函数 send的值给的是yield yield 后面是函数的返回值。
生成器优点:1、延迟计算,一次返回一个结果,对于处理大数据非常有用。 2、只能遍历一次。
4、协程:
协程,又称微线程,纤程。英文名Coroutine。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点类似CPU的中断。
4、用协程实现生产者消费者:
import time
def consumer(name):
print('开始吃包子')
while 1:
time.sleep(6)
x = yield
print('{}正在吃{}个包子'.format(name,x))
def producer():
con1.__next__()
con2.__next__()
i = 0
while 1:
print('做好了{}and{}包子'.format(i,i+1))
con1.send(i)
con2.send(i+1)
i += 2
if __name__ == '__main__':
con1 = consumer('A')
con2 = consumer('B')
producer()
首先调用con1.__next__(),con2.__next__()启动两个生成器;然后,一旦生产了东西,通过con1.send(i)切换到consumer执行consumer通过yield拿到消息,处理,又通过yield把结果传回;produce拿到consumer处理的结果,继续生产下一条消息;直到producer生产完毕。