Python yield的理解与简单测试
来源:互联网 发布:mac os 10.11镜像下载 编辑:程序博客网 时间:2024/05/29 08:23
在学习异步IO,会涉及到协程,最简单的协程,可以用yield来模拟,最初学习yield的时候就没搞太明白,今天看了些博客,终于搞得懂了。
下面给出一个作者的总结的知识点,让我理解了。http://www.jianshu.com/p/d09778f4e055,谢谢
主要的掌握
1.通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。
它的缺陷是所有数据都在内存中,如果有海量数据的话将会非常耗内存。
2.生成器是可以迭代的,但只可以读取它一次。因为用的时候才生成。比如 mygenerator = (x*x for x in range(3)),注意这里用到了(),它就不是数组,而上面的例子是[]。
3.我理解的生成器(generator)能够迭代的关键是它有一个next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常。可以用上面的mygenerator测试。
4.带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代,工作原理同上。
5.yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。
6.简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。
7.带有yield的函数不仅仅只用于for循环中,而且可用于某个函数的参数,只要这个函数的参数允许迭代参数。比如array.extend函数,它的原型是array.extend(iterable)。
8.send(msg)与next()的区别在于send可以传递参数给yield表达式,这时传递的参数会作为yield表达式的值(这里应该理解到yield表达式,它是一个表达式,而不仅仅yield产生一个值),而yield的参数是返回给调用者的值。——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10
9.send(msg)与next()都有返回值,它们的返回值是当前迭代遇到yield时,yield后面表达式的值,其实就是当前迭代中yield后面的参数。
10.第一次调用时必须先next()或send(None),否则会报错,send后之所以为None是因为这时候没有上一个yield(根据第8条)。可以认为,next()等同于send(None)。
#encoding:UTF-8def gener(): print "1" x=yield "hello" print "2","x=",x y=5+(yield x) print "3","y=",yg=gener()print g.next()#g.send(None)'''这里第一次调用时的两种方法输出:1hello #程序到yield就结束,下次调用时从断开处继续(这个特点会用在协程,异步IO,并发技术中)'''print g.send(5)'''继上一次断处执行print "2","x=",x y=5+(yield x)由于send(5),那么上一次yield表达式的值就位5,所以x=5然后运行到yield x,则输出yield后面的参数5'''print g.send(2)'''此时send(2),则上一次yield的表达式的值为2则y=7'''
二、使用yield实现协程
#coding=utf-8
__author__ = "Zhangxiaozi"
#!/usr/bin/python
def consumer():
r = ''
while True:
n = yield r #消费者通过yield表达式拿到消息,再把yield的参数当做反馈结果反馈给生产者
if not n:
print("not n...")
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
f = c.send(None) #第一次f等于''
print('[PRODUCER] Consumer first return: %s' % f)
n = 0
while n < 2:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
# 一旦产生东西就通过r = c.send(n)切换到消费者consumer执行
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
程序结果:
[PRODUCER] Consumer first return:
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
协程的说明:
注意到consumer函数是一个generator,把一个consumer传入produce后:
- 首先调用c.send(None)启动生成器;
- 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
- consumer通过yield拿到消息,处理,又通过yield把结果传回;
- produce拿到consumer处理的结果,继续生产下一条消息;
- produce决定不生产了,通过c.close()关闭consumer,整个过程结束。
整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。
阅读全文
1 0
- Python yield的理解与简单测试
- python yield 简单理解
- Python中yield的简单理解
- Python yield 的理解
- Python中yield的理解
- Python的yield相关理解
- JavaScript与python的yield
- Python中对于yield的个人理解
- python的迭代器、生成器、yield理解
- Python Scrapy中yield Request的理解
- 深入理解python的yield和generator
- python的迭代器iterator和生成器generator(关键字yield)的简单理解
- python之yield理解
- Python 深入理解yield
- Python 深入理解yield
- Python 深入理解yield
- Python 深入理解yield
- Python 深入理解yield
- Eclipse上Maven环境配置使用 (全)
- 剑指Offer 调整数组顺序使奇数位于偶数前面
- mongodb中的聚合
- 解决并发情况下库存减为负数问题
- 1092 回文字符串(最长公共子序列)
- Python yield的理解与简单测试
- java算法之简单的Reverse Integer
- log4j简单配置
- CCF-CSP 学生排队 JAVA 201703-2
- C# 多线程
- MySQL使用学习记录
- 【kong系列四】之插件篇
- 链家笔试:斐波那契数列中的第k个数
- 前台js页面定时显示弹窗消息提示