yield、send、threw、close
# coding: utf8
# 生成器
def gen(n):
for i in range(n):
yield i
g = gen(5) # 创建一个生成器
print(g) # <generator object gen at 0x10bb46f50>
print(type(g)) # <type 'generator'>
# 迭代生成器中的数据(只有执行for循环的时候,gen生成器才会返回yield后面的值,而且是一个一个的返回,这不同于return,全部返回来)
for i in g:
print(i)
#0 1 2 3 4
'''
next
generator.__next__():执行 for 时调用此方法,每次执行到 yield 就会停止,然后返回 yield 后面的值,
如果没有数据可迭代,抛出 StopIterator 异常,for 循环结束
'''
def gen1(n):
for i in range(n):
print('start')
yield i
print('end')
g = gen1(3) # 创建一个生成器
print(g.__next__()) # 0
print(g.__next__()) # 1
print(g.__next__()) # 2
print(g.__next__()) # StopIteration
'''
send (send 方法可以把外部的值传入生成器内部,从而改变生成器的状态)
当我们执行 g.send(-1) 时,相当于把 -1 传入到了生成器内部,然后赋值给了 yield 前面的 j,
此时 j = -1,然后这个方法就会 break 出来,不会继续迭代下去。
'''
def gen2():
i = 1
while True:
j = yield i
i *= 2
if j == -1:
break
g = gen2() # 创建一个生成器
print(g.__next__()) # 1
print(g.__next__()) # 2
print(g.__next__()) # 4
# send 把 -1 传入生成器内部 走到了 j = -1 这个分支
print(g.send(-1)) # StopIteration 迭代停止
'''
throw(外部除了可以向生成器内部传入一个值外,还可以传入一个异常,也就是调用 throw 方法)
'''
def gen3():
try:
yield 1
except ValueError:
yield 'ValueError'
finally:
print('finally')
g = gen3() # 创建一个生成器
print(g.__next__()) # 1
# 向生成器内部传入异常 返回ValueError
print(g.throw(ValueError))
# Output:
# 1
# ValueError
# finally
'''
close(生成器的 close 方法也比较简单,就是手动关闭这个生成器,关闭后的生成器无法再进行操作)
'''
g = gen()
print(g.close()) # 关闭生成器
print(g.__next__()) # 无法迭代数据
利用生成器做一个生产和消费协同并发:
# coding: utf8
def consumer():
i = None
while True:
# 拿到 producer 发来的数据
j = yield i
print('consume %s' % j)
def producer(c):
c.__next__()
for i in range(5):
print('produce %s' % i)
# 发数据给 consumer
c.send(i)
c.close()
c = consumer()
producer(c)