day4-生成器、迭代器

一、生成器

先看个列表生成式,[i*2 for i in range(10)]

像这样用列表生成式我们很容易创建一个数量庞大的列表,但是列表容量毕竟有限,我们有时候仅仅只需要知道列表前面一些元素,

而这些元素又可以通过某种算法推算得出。这种一边循环一边推算的机制,称之为生成器generator。

创建生成器:

方法一:把[]改成()

1 c = (i*2 for i in range(10))
2 c.__next__()

一般使用循环:

1 c = (i * 2 for x in range(10))
2 for n in c:
3     print(n)

ps: Python2调用的是next()方法,Python3调用的是__next__()方法

方法二:函数定义中包含yield关键字

斐波拉契数列

 1 def fib(max): #10
 2     n, a, b = 0, 0, 1
 3     while n < max: #n<10
 4         #print(b)
 5         #yield中断并返回当前状态
 6         yield b
 7         a, b = b, a + b
 8         #a = b     a =1, b=2, a=b , a=2,
 9         # b = a +b b = 2+2 = 4
10         n = n + 1
11     # 异常时打印的消息
12     return '---done---'
13 
14 f = fib(10)
15 #调用next方法
16 print f.__next__()
17 #一般使用循环取值 
18 for i in f:
19     print(i)
20     

ps:
这里的:a, b = b , a+b
等价于:
t = (b, a+b)
a = t[0]
b = t[1]

生成器generator和函数的执行流程不一样。

函数是顺序执行,遇到return语句或者最后一行函数语句就返回。

而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

生成器调用次数超出时需捕获StopIteration错误,返回值包含在StopIterationvalue中(try...except StopIteration as e:print e.value

通过生成器实现协程并行运算

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Alex Li'
 3 
 4 import time
 5 def consumer(name):
 6     print("%s 准备吃包子啦!" %name)
 7     while True:
 8        baozi = yield
 9 
10        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
11 
12 
13 def producer(name):
14     c = consumer('A')
15     c2 = consumer('B')
16     c.__next__()
17     c2.__next__()
18     print("老子开始准备做包子啦!")
19     for i in range(10):
20         time.sleep(1)
21         print("做了2个包子!")
22         c.send(i)
23         c2.send(i)
24 
25 producer("alex")

 

二、 迭代器

可迭代对象Iterable:可以直接作用于for循环的对象,分为两类

一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function

可以使用isinstance()判断一个对象是否是Iterable对象:

 

1 >>> isinstance((x for x in range(10)), Iterable)
2 True
3 >>> isinstance(100, Iterable)
4 False

 

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。

可以使用isinstance()判断一个对象是否是Iterator对象:

1 >>> from collections import Iterator
2 >>> isinstance((x for x in range(10)), Iterator)
3 True
4 >>> isinstance([], Iterator)
5 False
6 >>> isinstance({}, Iterator)
7 False
8 >>> isinstance('abc', Iterator)
9 False

生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter()函数:

1 >>> isinstance(iter([]), Iterator)
2 True
3 >>> isinstance(iter('abc'), Iterator)
4 True

小结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

 

posted @ 2017-06-12 23:47  不知所以  阅读(93)  评论(0)    收藏  举报