举例详解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脚本设置系统时间的两种方法
Feb 21 Python
itchat接口使用示例
Oct 23 Python
flask框架实现连接sqlite3数据库的方法分析
Jul 16 Python
Python常见内置高效率函数用法示例
Jul 31 Python
Python 新建文件夹与复制文件夹内所有内容的方法
Oct 27 Python
Python面向对象之类和对象实例详解
Dec 10 Python
Python单元测试unittest的具体使用示例
Dec 17 Python
python yield和Generator函数用法详解
Feb 10 Python
python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍
Feb 25 Python
jupyter notebook 写代码自动补全的实现
Nov 02 Python
详解Python中string模块除去Str还剩下什么
Nov 30 Python
浅析pandas随机排列与随机抽样
Jan 22 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抓取蜘蛛爬虫痕迹的示例代码
2016/09/30 PHP
phpcmsv9.0任意文件上传漏洞解析
2020/10/20 PHP
TNC vs BOOM BO3 第一场2.13
2021/03/10 DOTA
原生js拖拽(第一课 未兼容)拖拽思路
2013/03/29 Javascript
js脚本实现数据去重
2014/11/27 Javascript
node.js中的path.resolve方法使用说明
2014/12/08 Javascript
Jquery操作Ajax方法小结
2015/11/29 Javascript
JavaScript使ifram跨域相互访问及与PHP通信的实例
2016/03/03 Javascript
Bootstrap php制作动态分页标签
2016/12/23 Javascript
详解JavaScript树结构
2017/01/09 Javascript
面试常见的js算法题
2017/03/23 Javascript
js实现抽奖效果
2017/03/27 Javascript
老生常谈jacascript DOM节点获取
2017/04/17 Javascript
使用npm安装最新版本nodejs
2018/01/18 NodeJs
jQuery实现动态生成年月日级联下拉列表示例
2019/05/11 jQuery
[06:48]DOTA2-DPC中国联赛2月26日Recap集锦
2021/03/11 DOTA
Python提取网页中超链接的方法
2016/09/18 Python
在cmd中运行.py文件: python的操作步骤
2018/05/12 Python
python爬取哈尔滨天气信息
2018/07/14 Python
Python常见数据结构之栈与队列用法示例
2019/01/14 Python
为什么说Python可以实现所有的算法
2019/10/04 Python
详解Django CAS 解决方案
2019/10/30 Python
django有哪些好处和优点
2020/09/01 Python
Gerry Weber德国官网:优质女性时装,德国最大的时装公司之一
2019/11/02 全球购物
实习老师个人总结的自我评价
2013/09/28 职场文书
大专毕业生简历的自我评价
2013/10/20 职场文书
员工年终演讲稿
2014/01/03 职场文书
《守株待兔》教学反思
2014/03/01 职场文书
小学生暑假家长评语
2014/04/17 职场文书
2014年超市员工工作总结
2014/11/18 职场文书
初中生300字旷课检讨书
2014/11/19 职场文书
土地租赁协议书
2015/01/29 职场文书
2015年南京大屠杀纪念日活动总结
2015/03/24 职场文书
2015年三万活动总结
2015/03/25 职场文书
学校艾滋病宣传活动总结
2015/05/09 职场文书
活动主持人开场白
2015/05/28 职场文书