举例详解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调用cmd复制文件代码分享
Dec 27 Python
Python中类型检查的详细介绍
Feb 13 Python
python 3.5下xadmin的使用及修复源码bug
May 10 Python
Python WXPY实现微信监控报警功能的代码
Oct 20 Python
Python的条件表达式和lambda表达式实例
Jan 31 Python
Python Matplotlib实现三维数据的散点图绘制
Mar 19 Python
Windows平台Python编程必会模块之pywin32介绍
Oct 01 Python
Python手绘可视化工具cutecharts使用实例
Dec 05 Python
python 实现简单的FTP程序
Dec 27 Python
Python Numpy库常见用法入门教程
Jan 16 Python
python中使用input()函数获取用户输入值方式
May 03 Python
python状态机transitions库详解
Jun 02 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利用REFERER根居访问来地址进行页面跳转
2013/09/28 PHP
php根据日期判断星座的函数分享
2014/02/13 PHP
深入理解PHP 数组之count 函数
2016/06/13 PHP
PHP数组去重的更快实现方式分析
2018/05/09 PHP
php设计模式之适配器模式原理、用法及注意事项详解
2019/09/24 PHP
laravel-admin自动生成模块,及相关基础配置方法
2019/10/08 PHP
深入认识JavaScript中的函数
2007/01/22 Javascript
Z-Blog中用到的js代码
2007/03/15 Javascript
记录几个javascript有关的小细节
2007/04/02 Javascript
js将字符串转成正则表达式的实现方法
2013/11/13 Javascript
使用js实现数据格式化
2014/12/03 Javascript
javascript相关事件的几个概念
2015/05/21 Javascript
js仿黑客帝国字母掉落效果代码分享
2020/11/08 Javascript
JS+CSS实现电子商务网站导航模板效果代码
2015/09/10 Javascript
详解Webwork中Action 调用的方法
2016/02/02 Javascript
javascript创建cookie、读取cookie
2016/03/31 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
JS数组splice操作实例分析
2019/10/12 Javascript
解决在Vue中使用axios POST请求变成OPTIONS的问题
2020/08/14 Javascript
vue3.0自定义指令(drectives)知识点总结
2020/12/27 Vue.js
python实现动态数组的示例代码
2019/07/15 Python
python图片验证码识别最新模块muggle_ocr的示例代码
2020/07/03 Python
Python生成器传参数及返回值原理解析
2020/07/22 Python
基于python模拟bfs和dfs代码实例
2020/11/19 Python
应用心理学个人的求职信
2013/12/08 职场文书
中学运动会广播稿
2014/01/19 职场文书
美术教师自我鉴定
2014/02/12 职场文书
教师自我鉴定范文
2014/03/20 职场文书
施工质量承诺书范文
2014/05/30 职场文书
镇班子对照检查材料思想汇报
2014/09/24 职场文书
党校学习党性分析材料
2014/12/19 职场文书
八年级作文之一起的走过日子
2019/09/17 职场文书
Python爬虫:从m3u8文件里提取小视频的正确操作
2021/05/14 Python
Python使用OpenCV和K-Means聚类对毕业照进行图像分割
2021/06/11 Python
MongoDB数据库常用的10条操作命令
2021/06/18 MongoDB
MySQL分布式恢复进阶
2022/07/23 MySQL