举例详解Python中yield生成器的用法


Posted in Python onAugust 05, 2015

yield是生成的意思,但是在python中则是作为生成器理解,生成器的用处主要可以迭代,这样简化了很多运算模型(还不是很了解是如何简化的)。
yield是一个表达式,是有返回值的.
当一个函数中含有yield时,它不再是一个普通的函数,而是一个生成器.当该函数被调用时不会自动执行,而是暂停,见第一个例子:
例1:

>>> def mygenerator():
...  print 'start...'
...  yield 5
... 
>>> mygenerator()   //在此处调用,并没有打印出start...说明存在yield的函数没有被运行,即暂停
<generator object mygenerator at 0xb762502c>
>>> mygenerator().next()  //调用next()即可让函数运行.
start...
5
>>>

如一个函数中出现多个yield则next()会停止在下一个yield前,见例2:
例2:

>>> def mygenerator():
...  print 'start...'
...  yield 5
... 
>>> mygenerator()   //在此处调用,并没有打印出start...说明存在yield的函数没有被运行,即暂停
<generator object mygenerator at 0xb762502c>
>>> mygenerator().next()  //调用next()即可让函数运行.
start...
5
>>>

为什么yield 5会输出5,yield 23会输出23?
我们猜测可能是因为yield是表达式,存在返回值.
那么这是否可以认为yield 5的返回值一定是5吗?实际上并不是这样,这个与send函数存在一定的关系,这个函数实质上与next()是相似的,区别是send是传递yield表达式的值进去,而next不能传递特定的值,只能传递None进去,因此可以认为g.next()和g.send(None)是相同的。见例3:
例3:

>>> def fun():
...  print 'start...'
...  m = yield 5
...  print m
...  print 'middle...'
...  d = yield 12
...  print d
...  print 'end...'
... 
>>> m = fun()    //创建一个对象
>>> m.next()    //会使函数执行到下一个yield前
start...
5
>>> m.send('message')  //利用send()传递值
message     //send()传递进来的 
middle...
12
>>> m.next()
None      //可见next()返回值为空
end...
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

在multiprocess中的使用

python在处理数据的时候,memory-heavy 的数据往往会导致程序没办反运行或者运行期间服务器其他程序效率受到影响。这种情况往往会把数据集合变为通过genertor来遍历。

但同时如我们所知,generoter看似只能被单进程消费,这样效率很低。
generator 可以被pool.map消费。

看一下pool.py的源码。

for i, task in enumerate(taskseq):
  ...
  try:
   put(task)
  except IOError:
   debug('could not put task on queue')
   break

实际是先将generator全部消费掉放到queue中。然后通过map来并行。这样是解决了使用map来并行。

但是依然没有解决占用内存的问题。这里有两步占用内存。

  1.     第一步是全部消费掉的generator。
  2.     第二步并行运算全部data。

解决第一个问题,通过部分消费generator来达到。
解决第二个问题,可以通过imap来达到.

示例代码如下:

import multiprocessing as mp
import itertools
import time


def g():
 for el in xrange(50):
  print el
  yield el

import os

def f(x):
 time.sleep(1)
 print str(os.getpid()) +" "+ str(x)
 return x * x

if __name__ == '__main__':
 pool = mp.Pool(processes=4)    # start 4 worker processes
 go = g()
 result = []
 N = 11
 while True:
  g2 = pool.imap(f, itertools.islice(go, N))
  if g2:
   for i in g2:
    result.append(i)
    time.sleep(1)
  else:
   break
 print(result)

ps: 使用注意事项。在produce数据的时候,尽量少做操作,应为即使是map也是单线程的来消费数据。所以尽量把操作放到map中作。这样才能更好的利用多进程提高效率。

Python 相关文章推荐
python通过smpt发送邮件的方法
Apr 30 Python
python 将数据保存为excel的xls格式(实例讲解)
May 03 Python
python 编写简单网页服务器的实例
Jun 01 Python
django框架之cookie/session的使用示例(小结)
Oct 15 Python
解决python 无法加载downsample模型的问题
Oct 25 Python
pandas 透视表中文字段排序方法
Nov 16 Python
Python多进程fork()函数详解
Feb 22 Python
Python 可变类型和不可变类型及引用过程解析
Sep 27 Python
python config文件的读写操作示例
Sep 27 Python
TensorFlow tf.nn.conv2d实现卷积的方式
Jan 03 Python
Python GUI编程学习笔记之tkinter中messagebox、filedialog控件用法详解
Mar 30 Python
python 异步async库的使用说明
May 04 Python
Python中return语句用法实例分析
Aug 04 #Python
python函数形参用法实例分析
Aug 04 #Python
Python简明入门教程
Aug 04 #Python
将Python代码打包为jar软件的简单方法
Aug 04 #Python
python函数局部变量用法实例分析
Aug 04 #Python
python删除列表内容
Aug 04 #Python
解决Python传递中文参数的问题
Aug 04 #Python
You might like
咖啡知识 除了喝咖啡还有那些知识点
2021/03/06 新手入门
在PHP中使用XML
2006/10/09 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
PHP中字符安全过滤函数使用小结
2015/02/25 PHP
php查看网页源代码的方法
2015/03/13 PHP
使用ThinkPHP的自动完成实现无限级分类实例详解
2016/09/02 PHP
php结合md5的加密解密算法实例
2016/09/30 PHP
thinkPHP5.0框架API优化后的友好性分析
2017/03/17 PHP
js checkbox(复选框) 使用集锦
2009/04/28 Javascript
用循环或if语句从json中取数据示例
2014/08/18 Javascript
浅谈JavaScript函数节流
2014/12/09 Javascript
JavaScript实现DIV层拖动及动态增加新层的方法
2015/05/12 Javascript
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
2015/11/23 Javascript
js闭包引起的事件注册问题介绍
2016/03/29 Javascript
使用BootStrap进行轮播图的制作
2017/01/06 Javascript
jQuery实现radio第一次点击选中第二次点击取消功能
2017/05/15 jQuery
jquery仿京东商品放大浏览页面
2017/06/06 jQuery
jQuery实现返回顶部按钮和scroll滚动功能[带动画效果]
2017/07/05 jQuery
vue项目中api接口管理总结
2018/04/20 Javascript
详解解决小程序中webview页面多层history返回问题
2019/08/20 Javascript
Vue获取微博授权URL代码实例
2020/11/04 Javascript
vuex Module将 store 分割成模块的操作
2020/12/07 Vue.js
Python2.5/2.6实用教程 入门基础篇
2009/11/29 Python
Python函数可变参数定义及其参数传递方式实例详解
2015/05/25 Python
Python实现的从右到左字符串替换方法示例
2018/07/06 Python
django 配置阿里云OSS存储media文件的例子
2019/08/20 Python
pytorch torch.nn.AdaptiveAvgPool2d()自适应平均池化函数详解
2020/01/03 Python
OpenCV 使用imread()函数读取图片的六种正确姿势
2020/07/09 Python
麦德龙官方海外旗舰店:德国麦德龙超市
2017/12/23 全球购物
新媒传信软件测试面试题
2013/02/24 面试题
六年级数学教学反思
2014/02/03 职场文书
科技活动周标语
2014/10/08 职场文书
2014年生产管理工作总结
2014/12/23 职场文书
教师个人教学总结
2015/02/11 职场文书
民主评议党员个人自我评价
2015/03/03 职场文书
2015年学校安全工作总结
2015/04/22 职场文书