一、生成器的创建及使用
生成器比迭代器更节省内存空间,使用生成器,可以生成一个值的序列用于迭代,并且这个值的序列不是一次生成的,而是使用一个,再生成一个,的确可以使程序节省大量的内存损耗
创建生成器,需带有yield的函数,带有yield关键字的函数,本质上就是一个生成器
示例:
# 这是一个生成器对象
def myYield(n):
while n > 0:
print("开始生成...:")
yield n
print("完成一次...:")
n -= 1
# 实例化一个生成器对象,可以用变量进行直接引用
my_yield = myYield(3)
print("第一次调用__next()__方法")
result = my_yield.__next__()
print("第一次调用后,返回的值是:",result)
print("第二次调用__next()__方法")
result = my_yield.__next__()
print("第二次调用后,返回的值是:",result)
输出结果:
第一次调用__next()__方法
开始生成...:
第一次调用后,返回的值是: 3
第二次调用__next()__方法
完成一次...:
开始生成...:
第二次调用后,返回的值是: 2
总结:
- 每次调用__next()__方法,就会生成一次,同时返回n,执行到yield语句后,不会继续往下执行,且结束一次生成
- 第二次调用__next()__方法,就会从上一次结束执行的地方继续执行,执行到yield语句后,同时返回n,不会继续往下执行
创建一个能够接收外部参数的生成器,使用send方法向generator生成器进行传值
示例:
def myYield(n):
while n > 0:
rcv = yield n
print("接收到外部的值:",rcv)
n -= 1
if rcv is not None:
n = rcv
if __name__ == "__main__":
my_yield = myYield(3)
print("第一次调用__next__()的值:")
print(my_yield.__next__())
print("第二次调用__next__()的值:")
print(my_yield.__next__())
print("传给生成器一个值,重新初始化生成器。")
print("第一次调用__send__()外部传值修改生成器")
print(my_yield.send(10))
print("第三次调用__next__()的值:")
print(my_yield.__next__())
输出结果:
第一次调用__next__()的值:
3
第二次调用__next__()的值:
接收到外部的值: None
2
传给生成器一个值,重新初始化生成器。
第一次调用__send__()外部传值修改生成器
接收到外部的值: 10
10
第三次调用__next__()的值:
接收到外部的值: None
9
总结:
- 调用send()方法向传值,且生成器能正常接收成功,语法:rcv = yield,rcv则是send方法传递过来的值,若无任何参数,返回None
- 每次调用send()方法,生成器也会生成一次对应的数值,返回n,且运行到yeild语句后,停止执行
- 每次调用一次send(10)方法,传递的值只能被接收到一次,rcv=10,再次调用__next__()方法,rcv=None
二、协程的介绍
# -*- coding:utf-8 -*-
def consumer():
print("已经生成一个消费者")
while True:
print("消费者1号:等待接收处理任务...")
data = (yield)
print("消费者1号:收到任务:",data,"完成处理...")
def producer():
c = consumer()
c.__next__()
for i in range(3):
print("生产者1号:发送一个任务...","任务%s" % i)
c.send("任务%d" % i)
if __name__ == "__main__":
producer()
上述代码输出结果:
已经生成一个消费者
消费者1号:等待接收处理任务...
生产者1号:发送一个任务... 任务0
消费者1号:收到任务: 任务0 完成处理...
消费者1号:等待接收处理任务...
生产者1号:发送一个任务... 任务1
消费者1号:收到任务: 任务1 完成处理...
消费者1号:等待接收处理任务...
生产者1号:发送一个任务... 任务2
消费者1号:收到任务: 任务2 完成处理...
消费者1号:等待接收处理任务...