Python小程序

Python里的生成器

swofford posted @ 2010年10月16日 10:48 in Python , 2620 阅读

昨天看赖勇浩的一篇文章,讲的是生成器(具体是哪篇后来找不到了 =.=),前两天又在看这方面的内容,就稍微总结下。

我们都知道,在Python中定义一个函数可以用def,如果函数需要返回一个结果可以用return value,而如果返回的是一个结果集,可以用Python的集合类型,如列表。这里我们假设以列表返回。当列表不是很大的时候,还是很方便的,而如果要返回的数据非常多,将其放在一个列表中,会占用比较大的内存空间。Python为了解决这个问题引入了生成器。生成器每次返回列表中的一个结果,而不是将整个列表一起返回。相对于前者,生成器速度会慢一些,但是占用的空间会小一些。生成器之于列表,就相当于range()之于xrange(),或者是readlines()之于xreadline()(xreadline()在2.7中貌似没有……)

函数返回值是用return,而生成器返回是用yield,“yield语句会将函数关起,并向它的调用者返回一个值,但是保存足够的状态信息为了让其能够在函数从它挂起的地方回复。这能够允许这些函数不断的产生一系列的值,而不是一次计算所有的值,之后将值以类似列表之类的形式来返回。”“不过生成器函数也许也有一个return语句,这个语句就是用来终止产生值的。”《Python学习手册》第三版P383

代码说的更清楚点

def gensquares(N):
for i in range(N):
    yield i**2
x = gensquares(5)

gensquares()会生成0~N-1中每个数的平方,并依次返回,在IDLE中,print x会返回<generator object gensquares at 0x01202170>,而调用x.next()则会返回0~4的平方,第六次调用x.next()会返回StopIteration异常。

而这样单纯地用生成器只是返回生成器对象的地址,而不是一个集合,所以我们要把生成器放在列表解析里面,这样就有用多了:

for num in (x**2 for x in range(5)):
    print num,

for num in [x**2 for x in range(5)]:
    print num,

结果都是:0 1 4 9 16

注意:第一个函数用的是小括号,这样函数利用的就是生成器,而第二个是用的列表(这个例子有点囧,不过只为举例而用:),第一个的生成器形式是分5次依次返回0~4,而第二个列表形式是一次性返回[0, 1, 2, 3, 4]。这样可能看不出什么区别,但当返回的结果非常大时,生成器比列表占用的资源要少很多。

生成器同其他许多内置类型一样,支持迭代器,而其他很多支持迭代器的数据类型都可以产生生成器,这就是为什么遍历字典的时候不需要调用.keys(),遍历一个文件中的所有行不需要调用readlines()

for key in D:
    print key, D[key]

for line in open('test.txt'):
    print line,

PS:最近在看《Python学习手册》第三版,今天看到了模块一章,看的头昏脑胀,好像真的有点啰嗦了,看完写的这篇,好像我自己也变得啰嗦了 Orz....

PSS:初学Python,有错误的话请各位指出。

Avatar_small
Emma 说:
2023年2月01日 03:09

Generators are a great way to save memory space in Python when dealing with large results sets. By using generators instead of lists, you can iterate through the results diamonds rings near me one at a time, as opposed to loading the whole list into memory. While this may result in slower performance, it is worth it for the memory savings you get. Thanks to Python, we can now use generators to get the job done quickly and efficiently.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter