1、列表生成式
1 [i*2 for i in range(10)] 2 [fun(i) for i in range(10)]
2、生成器
1 # Author Qian Chenglong 2 3 #列表生成器 4 a=(i*2 for i in range(10)) 5 #a[1]#只是将算法存储了,只有在调用时才会生成相应的数据,不能直接读取 6 a.__next__()#生成器只能一个一个往后取,且只存储当前值 7 8 #函数生成器 9 10 # def fib(max): 11 # n,a,b = 0,0,1 12 # while n < max: 13 # print(b) 14 # a,b = b,a+b 15 # n += 1 16 # return 'done' 17 18 #要把fib函数变成generator,只需要把print(b)改为yield b就可以了 19 def fib(max): 20 n,a,b = 0,0,1 21 while n < max: 22 #print(b) 23 yield b 24 a,b = b,a+b 25 n += 1 26 return 'done'#异常时存储的消息 27 28 g=fib(10) 29 print(g.__next__()) 30 #这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间当需要再重新调用这个函数,从上次yield的下一句开始执行。 31 32 #生成器保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误(异常)。 33 34 #异常处理 35 g = fib(6) 36 while True: 37 try: 38 x = next(g) 39 print('g:', x) 40 41 except StopIteration as e: 42 print('Generator return value:', e.value) 43 break 44 45 #通过生成器实现协程并行运算 46 import time 47 def consumer(name): 48 print("%s 准备吃包子啦!" %name) 49 while True: 50 baozi = yield 51 52 print("包子[%s]来了,被[%s]吃了!" %(baozi,name)) 53 54 55 def producer(name): 56 c = consumer('A') 57 c2 = consumer('B') 58 c.__next__() 59 c2.__next__() 60 print("老子开始准备做包子啦!") 61 for i in range(10): 62 time.sleep(1) 63 print("做了2个包子!") 64 c.send(i) 65 c2.send(i)#把i的值传给yield,并到下一个yield 66 67 producer("Dragon")
3、迭代器
我们已经知道,可以直接作用于for
循环的数据类型有以下几种:
一类是集合数据类型,如list
、tuple
、dict
、set
、str
等;
一类是generator
,包括生成器和带yield
的generator function。
这些可以直接作用于for
循环的对象统称为可迭代对象:Iterable
。
可以使用isinstance()
判断一个对象是否是Iterable
对象:
>>> from collections import Iterable >>> isinstance([], Iterable) True >>> isinstance({}, Iterable) True >>> isinstance('abc', Iterable) True >>> isinstance((x for x in range(10)), Iterable) True >>> isinstance(100, Iterable) False
*可以被next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
一般来说:生成器就是迭代器,迭代器不一定是生成器(下面不用看了,越看越不懂)
生成器都是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
你可能会问,为什么list
、dict
、str
等数据类型不是Iterator
?
这是因为Python的Iterator
对象表示的是一个数据流,Iterator对象可以被next()
函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration
错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()
函数实现按需计算下一个数据,所以Iterator
的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator
甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。