http://blog.csdn.net/scelong/article/details/6969276

生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。

生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

生成器的特点

生成器是一个函数,而且函数的参数都会保留。

迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的

在python中,yield就是这样的一个生成器。

yield 生成器的运行机制:

当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把

yield 的参数给你,之后生成器就不会往下继续运行。 当你问他要下一个数时,他会从上次的状态。开始运行,直至出现yield语句,把参数给你,之后停下。如此反复 直至退出函数。(以上关于yield的描述,在后面列举一个简单的例子来解释这段话)

yield的使用

在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器,它的执行会和其他普通的函数有很多不同,函数返回的是一个对象,而不是你平常 所用return语句那样,能得到结果值。如果想取得值,那得调用next()函数,如:

  1. c = h() #h()包含了yield关键字
  2. #返回值
  3. c.next()

每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。

下面,来看看以下的例子代码吧,是用来说明yield运行机制的。

  1. def fib(max):
  2. a, b = 1, 1
  3. while a < max:
  4. yield a #generators return an iterator that returns a stream of values.
  5. a, b = b, a+b

程序运行:

  1. for n in fib(15):
  2. print n

从前面的运行机制描述中,可以获知,程序运行到yield这行时,就不会继续往下执行。而是返回一个包含当前函数所有参数的状态的iterator对象。目的就是为了第二次被调用时,能够访问到函数所有的参数值都是第一次访问时的值,而不是重新赋值。

程序第一次调用时:

  1. def fib(max):
  2. a, b = 1, 1
  3. while a < max:
  4. yield a #这时a,b值分别为1,1,当然,程序也在执行到这时,返回
  5. a, b = b, a+b

程序第二次调用时:

从前面可知,第一次调用时,a,b=1,1,那么,我们第二次调用时(其实就是调用第一次返回的iterator对象的next()方法),程序跳到yield语句处,

执行a,b = b, a+b语句,此时值变为:a,b = 1, (1+1) => a,b = 1, 2

程序继续while循环,当然,再一次碰到了yield a 语句,也是像第一次那样,保存函数所有参数的状态,返回一个包含这些参数状态的iterator对象。

等待第三次的调用....

  1. def fib(max):
  2. a, b = 1, 1
  3. while a < max:
  4. yield a
  5. a, b = b, a+b

通过上面的分析,可以一次类推的展示了yield的详细运行过程了!

通过使用生成器的语法,可以免去写迭代器类的繁琐代码,如,上面的例子使用迭代类来实现,代码如下:

  1. class Fib:
  2. def __init__(self, max):
  3. self.max = max
  4. def __iter__(self):
  5. self.a = 0
  6. self.b = 1
  7. return self
  8. def next(self):
  9. fib = self.a
  10. if fib > self.max:
  11. raise StopIteration
  12. self.a, self.b = self.b, self.a + self.b
  13. return fib

yield其他例子展示:排列,组合

#生成全排列

    1. def perm(items, n = None):
    2. if n is None:
    3. n = len(items)
    4. for i in range(len(items)):
    5. v = items[i:i+1]
    6. if n==1:
    7. yield v
    8. else:
    9. rest = items[:i] + items[i+1:]
    10. for p in perm(rest, n-1):
    11. yield v + p
    12. def comb(items, n = None):
    13. if n is None:
    14. n = len(items)
    15. else:
    16. for i in range(len(items)):
    17. v = items[i:i+1]
    18. if 1 == n:
    19. yield v
    20. else:
    21. rest = items[i+1:]
    22. for c in comb(rest, n-1):
    23. yield v + c

(转) Python Generators(生成器)——yield关键字的更多相关文章

  1. Python Generators(生成器)--yield

    参考:http://blog.csdn.net/scelong/article/details/6969276 Python生成器 什么是python生成器,意思是带有一个yield语句的函数,既然它 ...

  2. Python:笔记(7)——yield关键字

    Python:笔记(7)——yield关键字 yield与生成器 所谓生成器是一个函数,它可以生成一个值的序列,以便在迭代中使用.函数使用yield关键字可以定义生成器对象. 一个例子 我们调用该函数 ...

  3. 解析Python中的yield关键字

    前言 python中有一个非常有用的语法叫做生成器,所利用到的关键字就是yield.有效利用生成器这个工具可以有效地节约系统资源,避免不必要的内存占用. 一段代码 def fun(): for i i ...

  4. [PY3]——函数——生成器(yield关键字)

    函数—生成器篇 1. 认识和区分可迭代or生成器 1.1 可迭代对象 当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象 当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代 ...

  5. python中的yield关键字

    yield关键字一直困扰了我很久,一直也没有弄明白,现在将暂时理解的yield记录如下,供参考: 关键词:可迭代对象,生成器,迭代器 一.可迭代对象: 可迭代对象:可迭代对象是一个泛称,只要可以用fo ...

  6. 深入理解python中的yield关键字

    想必大家都看过这样的代码: 上面的这段代码会计算0-9的平方并打印出来. 那么问题来了,这段代码和我们要说的东西有什么区别呢? 这里的关键字,yield,我在前面的文章里已经发过了.那么yield是什 ...

  7. python yield 关键字

    最近看代码看到python里面的yield关键字,和我之前接触的语言好像都没有来着,我就查了查它的含义,大概理解如下: >>> def createGenerator(): ... ...

  8. PHP性能优化利器:生成器 yield理解

    如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显.但是,生成 ...

  9. Python列表生成器

    本篇将介绍python生成器,更多内容请参考:python学习指南 前言 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不 ...

随机推荐

  1. line-height 与垂直居中!

    在此之前,对于line-height 与垂直居中的问题,经常碰到. 比如,图片与span在同一个box中的时候,竟然会各种偏移.要想达到理想的效果真的是各种难. 有时间,决定认真的啃一啃. 一 lin ...

  2. [转载] ACE 组播校验和出错问题解决

    源地址:http://yuanmuqiuyu2000.blog.sohu.com/140904942.html 使用ACE框架写了个组播简单的测试工具,但是测试过程中,总是发现udp校验和出错的信息. ...

  3. MyEclipse 2015 CI

    系统 win8.1 MyEclipse 2015 CI 激活后可用 激活工具 地址:http://download.csdn.net/detail/trep10000/8305577

  4. shell脚本接收输入

    shell脚本接受输入 while read var do cat logs | grep IconsendRedirect | grep $var | awk -F'\t' '{print $8}' ...

  5. 一个简单的ObjC和JavaScript交互工具

    https://github.com/changjianfeishui/XBWebBridge ObjectiveC与Js交互是常见的需求,可对于新手或者所谓的高手而言,其实并不是那么简单明了.这里只 ...

  6. iOS开发--提交github代码

    将的SampleTable例子提交到github 具体步骤如下: a. 首先登陆github b. 创建新的reponsitory name, description c. 打开terminal, c ...

  7. 开放api设计资料收藏

    REST设计 api设计范例http://www.ibm.com/developerworks/cn/web/1103_chenyan_restapi/index.html?ca=drs http:/ ...

  8. java socket实现全双工通信

    java socket实现全双工通信 单工.半双工和全双工的定义 如果在通信过程的任意时刻,信息只能由一方A传到另一方B,则称为单工. 如果在任意时刻,信息既可由A传到B,又能由B传A,但只能由一个方 ...

  9. 5、java反射基础

    Class对象: Class对象记录了所有与类相关的信息,当类加载器从文件系统中加载.class文件到JVM中的同时会为每一个类创建一个Class对象.通过Class对象可以获取到类的属性.方法.构造 ...

  10. SQL Service Database BACKUP & RESTORE

    1. 完整恢复模式下的数据库备份 USE master; ALTER DATABASE AdventureWorks2012 SET RECOVERY FULL; GO -- Back up the ...