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错误,返回值包含在StopIteration的value中(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对象。

浙公网安备 33010602011771号