首页 > 代码库 > python成长之路12——生成器和迭代器

python成长之路12——生成器和迭代器

一. 什么是生成器和迭代器

   使用一个可迭代的对象比一个列表的好处:

     还记得前面的filter和map吗,他们的返回值是一个相应的对象,我们可以循环这个对象,就取到了每个对象元素,而且取完之后,这个元素就没啦,一边取值,一边垃圾回收,这样相对于返回值直接是一个列表,就大大的节省了内存。因为如果返回值是一个长度几万几十万的列表,会一下子在内存里开辟那么多的内存空间,但是如果生成的是一个filter或者map对象,就没有这个担心啦。

  我们用一个小例子来进行对比:

技术分享
 1 #要用python2.7的环境
 2 #py3中range和xrange合并啦,不再有xrange,range的返回值是range对象,不再是list
 3 
 4 ret=range(0,10)
 5 print ret
 6 print type(ret)
 7 
 8 ret=xrange(0,10)
 9 print ret
10 print type(ret)
11 
12 执行结果:
13 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
14 <type list>
15 xrange(10)
16 <type xrange>
17 
18 #可以明显看出生成一个可迭代的对象要比生成一个list对内存的占用少的多,xrange的话,取完一个值,用完之后,就会垃圾回收。
range和xrange

      生成器就可以实现这个功能。那么什么是生成器呢?

      生成器是一次生成一个值的特殊类型函数。标志性的单词就是yield。

  迭代器就是利用next来从生成器里取数据。

技术分享
 1 def f1():
 2     print("生成第一个数")
 3     yield 1
 4     print("生成第二个数")
 5     yield 2
 6     print("生成第三个数")
 7     yield 3
 8 ret=f1()
 9 #执行f1()的时候,3个print都没有输出,生成器是一种特殊的函数
10 print(ret)
11 #生成器生成的ret是一个生成器对象,这个对象可以迭代
12 print("*"*10)
13 print(list(ret))
14 print(list(ret))
15 
16 执行结果:
17 <generator object f1 at 0x102189c50>
18 **********
19 生成第一个数
20 生成第二个数
21 生成第三个数
22 [1, 2, 3]
23 []
24 
25 def f1():
26     print("生成第一个数")
27     yield 1
28     print("生成第二个数")
29     yield 2
30     print("生成第三个数")
31     yield 3
32 ret=f1()
33 #生成器可以配合__next__使用
34 r1=ret.__next__()
35 print(r1)
36 #r1:ret.__next__() 会找到函数中的第一个yield,执行函数到这个yield为止,并将yield后面的数据返回
37 r2=ret.__next__()
38 print(r2)
39 #r2:ret.__next__() 会执行上一个yield下面的代码直到遇到下一个yield,同上会返回yield后面的数据
40 
41 执行结果:
42 生成第一个数
43 1
44 生成第二个数
45 2
yield

注意:实际使用的时候是不需要我们一个一个的_next_的,for循环帮我们做了next,也可以说for循环封装了迭代器。

二. 生成器小例子

技术分享
 1 def zyrange(m,n):
 2     while True:
 3         yield m
 4         m+=1
 5         if m == n:
 6             break
 7 
 8 for i in zyrange(4,10):
 9     print(i)
10 
11 执行结果:
12 4
13 5
14 6
15 7
16 8
17 9
使用生成器实现range的功能

 

python成长之路12——生成器和迭代器