举例详解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在命令行下使用google翻译(带语音)
Jan 16 Python
Python写的Socks5协议代理服务器
Aug 06 Python
Python实现对字符串的加密解密方法示例
Apr 29 Python
Python列表list解析操作示例【整数操作、字符操作、矩阵操作】
Jul 25 Python
Python3 处理JSON的实例详解
Oct 29 Python
Python实现的简单排列组合算法示例
Jul 04 Python
python 数字类型和字符串类型的相互转换实例
Jul 17 Python
python输出电脑上所有的串口名的方法
Jul 02 Python
Python内置方法实现字符串的秘钥加解密(推荐)
Dec 09 Python
Python的对象传递与Copy函数使用详解
Dec 26 Python
K最近邻算法(KNN)---sklearn+python实现方式
Feb 24 Python
教你怎么用Python selenium操作浏览器对象的基础API
Jun 23 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下获取上个月、下个月、本月的日期(strtotime,date)
2014/02/02 PHP
php smarty模板引擎的6个小技巧
2014/04/24 PHP
跟我学Laravel之请求(Request)的生命周期
2014/10/15 PHP
Linux安装配置php环境的方法
2016/01/14 PHP
关于ThinkPHP中的异常处理详解
2018/05/11 PHP
Prototype使用指南之selector.js
2007/01/10 Javascript
js 自定义的联动下拉框
2010/02/07 Javascript
关于Ext中form移除textfield方法:hide(),setVisible(false),remove()
2010/12/02 Javascript
各种常用的JS函数整理
2013/10/25 Javascript
JQUERY表单暂存功能插件分享
2016/02/23 Javascript
jQuery在header中设置请求信息的方法
2017/03/06 Javascript
Node.js 使用AngularJS的方法示例
2018/05/11 Javascript
layer设置maxWidth及maxHeight解决方案
2019/07/26 Javascript
JavaScript图像放大镜效果实现方法详解
2020/06/28 Javascript
利用Python中的输入和输出功能进行读取和写入的教程
2015/04/14 Python
Python的条件语句与运算符优先级详解
2015/10/13 Python
Python 使用PIL numpy 实现拼接图片的示例
2018/05/08 Python
NumPy.npy与pandas DataFrame的实例讲解
2018/07/09 Python
小白入门篇使用Python搭建点击率预估模型
2018/10/12 Python
pyqt5 QScrollArea设置在自定义侧(任何位置)
2019/09/25 Python
Python 实现打印单词的菱形字符图案
2020/04/12 Python
使用Keras中的ImageDataGenerator进行批次读图方式
2020/06/17 Python
Selenium python时间控件输入问题解决方案
2020/07/22 Python
python 下划线的不同用法
2020/10/24 Python
美丽的现代设计家具:2Modern
2018/07/26 全球购物
Carter’s OshKosh加拿大:购买婴幼儿服装和童装
2018/11/27 全球购物
SQL里面如何插入自动增长序列号字段
2012/03/29 面试题
社区领导班子四风问题原因分析及整改措施
2014/09/28 职场文书
办公室主任岗位职责范本
2015/03/31 职场文书
幼儿园老师工作总结2015
2015/05/22 职场文书
酒桌上的开场白
2015/06/01 职场文书
寻找成龙观后感
2015/06/12 职场文书
优秀员工演讲稿
2019/06/21 职场文书
2019年第四季度财务部门工作计划
2019/11/02 职场文书
vue3使用vue-router的完整步骤记录
2021/06/20 Vue.js
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL