举例详解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的单元测试
Apr 28 Python
详解Python3中yield生成器的用法
Aug 20 Python
Python获取某一天是星期几的方法示例
Jan 17 Python
python3.x上post发送json数据
Mar 04 Python
python3 图片referer防盗链的实现方法
Mar 12 Python
Python中defaultdict与lambda表达式用法实例小结
Apr 09 Python
Python通过cv2读取多个USB摄像头
Aug 28 Python
flask 实现token机制的示例代码
Nov 07 Python
python 根据列表批量下载网易云音乐的免费音乐
Dec 03 Python
解决pycharm安装scrapy DLL load failed:找不到指定的程序的问题
Jun 08 Python
Python OpenCV实现传统图片格式与base64转换
Jun 13 Python
Python利用capstone实现反汇编
Apr 06 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+javascript液晶时钟
2006/10/09 PHP
php重定向的三种方法分享
2012/02/22 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
2017/06/21 PHP
PHP钩子与简单分发方式实例分析
2017/09/04 PHP
PHP预定义超全局数组变量小结
2018/08/20 PHP
javascript 函数参数限制说明
2010/11/19 Javascript
基于jQuery实现的Ajax 验证用户名是否存在的实现代码
2011/04/06 Javascript
jQuery-onload让第一次页面加载时图片是淡入方式显示
2012/05/23 Javascript
jquery操作select大全
2014/04/25 Javascript
jQuery文件上传插件Uploadify使用指南
2014/06/05 Javascript
javascript实现的平方米、亩、公顷单位换算小程序
2014/08/11 Javascript
原生javascript实现Tab选项卡切换功能
2015/01/12 Javascript
JavaScript 异常处理 详解
2015/02/06 Javascript
JS当前页面登录注册框,固定DIV,底层阴影的实例代码
2016/09/29 Javascript
文件上传,iframe跨域数据提交的实现
2016/11/18 Javascript
bootstrap实现每隔5秒自动轮播效果
2016/12/20 Javascript
JavaScript基础之流程控制语句的用法
2017/08/31 Javascript
jQuery zTree 异步加载添加子节点重复问题
2017/11/29 jQuery
30分钟快速入门掌握ES6/ES2015的核心内容(下)
2018/04/18 Javascript
关于Vue中$refs的探索浅析
2020/11/05 Javascript
python logging类库使用例子
2014/11/22 Python
pycharm远程调试openstack代码
2017/11/21 Python
pandas数据处理基础之筛选指定行或者指定列的数据
2018/05/03 Python
Python OpenCV调用摄像头检测人脸并截图
2020/08/20 Python
使用pandas 将DataFrame转化成dict
2019/12/10 Python
Python中random模块常用方法的使用教程
2020/10/04 Python
CSS3过渡transition效果实例介绍
2016/05/03 HTML / CSS
使用phonegap进行本地存储的实现方法
2017/03/31 HTML / CSS
区三好学生主要事迹
2014/01/30 职场文书
宣传保护环境的公益广告词
2014/03/13 职场文书
《最大的麦穗》教学反思
2014/04/17 职场文书
学习党的群众路线教育实践活动剖析材料
2014/10/13 职场文书
写自招自荐信的绝招!
2019/04/19 职场文书
2020优秀员工演讲稿(三篇)
2019/10/17 职场文书
解决Django transaction进行事务管理踩过的坑
2021/04/24 Python
Python OpenCV实现图像模板匹配详解
2022/04/07 Python