关于Python中的yield

原创 2016年08月29日 12:50:16

http://www.cnblogs.com/tqsummer/archive/2010/12/27/1917927.html


关于Python中的yield

在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor)。

一、迭代器(iterator)

在Python中,for循环可以用于Python中的任何类型,包括列表、元祖等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器

迭代器是一个实现了迭代器协议的对象,Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration。任何这类的对象在Python中都可以用for循环或其他遍历工具迭代,迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开。

使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。

比如要逐行读取一个文件的内容,利用readlines()方法,我们可以这么写:


1
2

for line in open("test.txt").readlines():
print line

这样虽然可以工作,但不是最好的方法。因为他实际上是把文件一次加载到内存中,然后逐行打印。当文件很大时,这个方法的内存开销就很大了。

利用file的迭代器,我们可以这样写:


1
2

for line in open("test.txt"):   #use file iterators
print line

这是最简单也是运行速度最快的写法,他并没显式的读取文件,而是利用迭代器每次读取下一行。

二、生成器(constructor)

生成器函数在Python中与迭代器协议的概念联系在一起。简而言之,包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口。函数也许会有个return语句,但它的作用是用来yield产生值的。

不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效


1
2
3
4
5
6
7
8

>>> def g(n):
... for i in range(n):
... yield i **2
...
>>> for i in g(5):
... print i,":",
...
0 : 1 : 4 : 9 : 16 :

要了解他的运行原理,我们来用next方法看看:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

>>> t = g(5)
>>> t.next()
0
>>> t.next()
1
>>> t.next()
4
>>> t.next()
9
>>> t.next()
16
>>> t.next()
Traceback (most recent call last):
File "", line 1, in <</span>module>
StopIteration

在运行完5次next之后,生成器抛出了一个StopIteration异常,迭代终止。
再来看一个yield的例子,用生成器生成一个Fibonacci数列:


1
2
3
4
5
6
7
8
9
10

def fab(max):
a,b = 0,1
while a <</span> max:
yield a
a, b = b, a+b
 
>>> for i in fab(20):
... print i,",",
...
0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 ,

看到这里应该就能理解生成器那个很抽象的概念了吧~~

感觉跟递归很像。


下面我们用yield来读文件:

随便建一个文件类似

1

2

3

一般我们读文件可以这样读

def read(file):

        with open(file) as f:

                for line in f.readlines():

                        print line

if __name__ == '__main__':

read("inputFile.txt")

但其实readlines这样子一下全读进来了,占内存。

我们用yield读

def read(file):

        with open(file) as f:

                for line in f:

                        yield line.strip()



if __name__ == '__main__':

        reader = read("inputFile.txt")

        line = reader.next()

        while line:

                line = reader.next()

                print line


或者这样
def read(file):
        with open(file) as f:
                for line in f:
                        yield line.strip()


if __name__ == '__main__':
        reader = read("inputFile.txt")
        for line in reader:
                print line

Python中的yield

其实一开始并不想学这个用法。但是随着教材往下看,总是能碰到yield这个东西,导致什么都看不下去。神烦的不行。于是专门拿出来啃一下 http://pyzh.readthedocs.org/en/lat...
  • u012671171
  • u012671171
  • 2014年12月26日 11:57
  • 11836

python的关键字yield有什么作用?

要理解yiled还需要理解生成器,而要理解生成器,首先需要理解迭代器。 迭代器: 所有你可以用在for...in...语句中的都是可迭代的:比如lists,strings,files...因为...
  • yubotianxiao
  • yubotianxiao
  • 2016年05月26日 07:33
  • 2260

十二、Python的yield用法与原理

翻了一篇workflow上关于yield的用法,翻的有点烂,在这里贻笑大方了,慢慢来,总是期待着一点一点的进步。 为了理解yield的机制,我们需要理解什么是生成器。在此之前先介绍迭代器iter...
  • alvine008
  • alvine008
  • 2015年02月02日 16:21
  • 44170

浅谈Python中的yield表达式

浅谈Python协程中的yield表达式python生成器python中生成器是迭代器的一种,使用yield返回函数值。每次调用yield会暂停,而可以使用next()函数和send()函数可以恢复生...
  • u014683535
  • u014683535
  • 2016年06月25日 11:26
  • 2762

python3 yield

本篇博客转载了点击打开链接,又加上了自己的一点理解 深入理解yield yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法。 只是粗...
  • Haskei
  • Haskei
  • 2017年02月07日 13:45
  • 3273

python中yield和return对比

相同点功能都是返回程序执行结果区别yield返回执行结果并不中断程序执行,return在返回执行结果的同时中断程序执行。...
  • zsl10
  • zsl10
  • 2016年09月28日 16:22
  • 2494

python中yield函数用法详解

yeild简单来说就是一个生成器,生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。\quad生成器是...
  • q__y__L
  • q__y__L
  • 2016年02月19日 17:49
  • 1913

python迭代器、生成器和yield语句

http://blog.csdn.net/pipisorry/article/details/22107553一、迭代器(iterator)迭代器:是一个实现了迭代器协议的对象,Python中的迭代器...
  • pipisorry
  • pipisorry
  • 2014年12月22日 21:08
  • 3278

提高你的Python: 解释yield和Generators(生成器)

协程与子例程 我们调用一个普通的Python函数时,一般是从函数的第一行代码开始执行,结束于return语句、异常或者函数结束(可以看作隐式的返回None)。一旦函数将控制权交还给调用者,就意味着全...
  • chenyulancn
  • chenyulancn
  • 2017年09月04日 10:28
  • 263

python yield 与 yield from

1、yield使用 1)函数中使用yield,可以使函数变成生成器。一个函数如果是生产一个数组,怎么必须把数据存储在内存中,如果使用生成器,则在调用的时候才生成数据,可以节省内存。 2)生成器方法...
  • chenbin520
  • chenbin520
  • 2017年09月27日 12:02
  • 2058
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于Python中的yield
举报原因:
原因补充:

(最多只允许输入30个字)