举例详解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 ORM框架SQLAlchemy学习笔记之安装和简单查询实例
Jun 10 Python
从头学Python之编写可执行的.py文件
Nov 28 Python
Python爬虫之pandas基本安装与使用方法示例
Aug 08 Python
python读取word 中指定位置的表格及表格数据
Oct 23 Python
Pandas数据离散化原理及实例解析
Nov 16 Python
Python socket聊天脚本代码实例
Jan 02 Python
浅谈python3 构造函数和析构函数
Mar 12 Python
解决python 执行sql语句时所传参数含有单引号的问题
Jun 06 Python
Python 使用生成器代替线程的方法
Aug 04 Python
python 线程的五个状态
Sep 22 Python
Python包资源下载路径报404解决方案
Nov 05 Python
Python使用OpenCV实现虚拟缩放效果
Feb 28 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
PHP的PSR规范中文版
2013/09/28 PHP
PHP把网页保存为word文件的三种方法
2014/04/01 PHP
ThinkPHP的L方法使用简介
2014/06/18 PHP
PHP使用GIFEncoder类处理gif图片实例
2014/07/01 PHP
PHP实现视频文件上传完整实例
2014/08/28 PHP
初识通用数据库操作类――前端easyui-datagrid,form(php)
2015/07/31 PHP
Laravel框架Eloquent ORM修改数据操作示例
2019/12/03 PHP
javascript类继承机制的原理分析
2009/09/12 Javascript
jQuery中需要注意的细节问题小结
2011/12/06 Javascript
JS多物体 任意值 链式 缓冲运动
2012/08/10 Javascript
js实现在文本框光标处添加字符的方法介绍
2012/11/24 Javascript
jQuery中使用Ajax获取JSON格式数据示例代码
2013/11/26 Javascript
javascript移出节点removeChild()使用介绍
2014/04/03 Javascript
jQuery获取选中内容及设置元素属性的方法
2014/07/09 Javascript
jQuery中removeClass()方法用法实例
2015/01/05 Javascript
jQuery 选择器详解
2015/01/19 Javascript
PHPExcel中的一些常用方法汇总
2015/01/23 Javascript
JavaScript使用push方法添加一个元素到数组末尾用法实例
2015/04/06 Javascript
JS实现探测网站链接的方法【测试可用】
2016/11/08 Javascript
JavaScript的兼容性与调试技巧
2016/11/22 Javascript
JavaScript交换两个变量值的七种解决方案
2016/12/01 Javascript
Vuejs在v-for中,利用index来对第一项添加class的方法
2018/03/03 Javascript
基于vue和react的spa进行按需加载的实现方法
2018/09/29 Javascript
使用Vue.set()方法实现响应式修改数组数据步骤
2019/11/09 Javascript
你不知道的 TypeScript 高级类型(小结)
2020/08/28 Javascript
结合CSS3的布局新特征谈谈常见布局方法
2016/01/22 HTML / CSS
荷兰网上买鞋:MooieSchoenen.nl
2017/09/12 全球购物
大学毕业后的十年规划
2014/01/07 职场文书
幼儿园教学随笔感言
2014/02/23 职场文书
《美丽的田园》教学反思
2014/03/01 职场文书
2014镇副书记群众路线专题民主生活会思想汇报
2014/09/23 职场文书
房产电话营销开场白
2015/05/29 职场文书
python制作图形界面的2048游戏, 基于tkinter
2021/04/06 Python
详解Python 3.10 中的新功能和变化
2021/04/28 Python
springboot 多数据源配置不生效遇到的坑及解决
2021/11/17 Java/Android
element tree树形组件回显数据问题解决
2022/08/14 Javascript