一 . 生成器
1.介绍
通过列表生成式,可以直接创建一个列表,但是受内存限制,列表容量是有限的。
a = [i*2 for i in range(10000)
print (a)
如果列表元素可以按照某种算法推算出来,是否可以在循环的过程中不断推算出后续的元素?
这样就不必创建完整的list,从而俭省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器,generator.
a = (i*2 for i in range(10000))
for i in a:
print (i)
generator比较强大,但是如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
比如:斐波那契数列,除了第一个和第二个数之外,任意的数都可有前面两个数相加得到(1,1,2,3,5,8,......)
1 def fib(max):
2 n, a, b = 0, 0, 1
3 while n < max: #n只是控制循环
4 print(b)
5 a, b = b, a + b
6
7 # 相当于:t = (b, a + b) (t是一个元组)
8 # a = t[0]
9 # b = t[1]
10 #不等价于下面的
11 #a = b a = 1,b = 2,a = b, a = 2
12 #b = a +b ,b = 2 + 2 = 4
13
14 n=n+1
15 return 'done'
16 fib(100) #生成100斐波那契数
1 def fib(max):
2 n, a, b = 0, 0, 1
3 while n < max: #n只是控制循环
4 #print(b)
5 yield b #就变成生成器了
6 a, b = b, a + b
7
8 # 相当于:t = (b, a + b) (t是一个元组)
9 # a = t[0]
10 # b = t[1]
11 #不等价于下面的
12 #a = b a = 1,b = 2,a = b, a = 2
13 #b = a +b ,b = 2 + 2 = 4
14
15 n=n+1
16 return 'done' #异常的时候打印的一个信息
17 f = fib(10) #生成100斐波那契数
18 print(f.__next__())
19 print(f.__next__())
20 print("_________") #函数想停就停,随意进出
21 print(f.__next__())
22 print(f.__next__())
23 print(f.__next__())
24 print("=====star loop======")
25 for i in f:
26 print(i)
补充:
异常捕捉;
还可以通过yield 实现在单线程的情况下实现并发运算的效果。
1 import time
2 def consumer(name): #消费者
3 print("%s 准备吃包子啦!" %name)
4 while True:
5 baozi = yield
6
7 print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
8
9 c = consumer("xiaolai")
10 c.__next__() #只是为了打印print("%s 准备吃包子啦!" %name)
11
12 def producer(name): #生产者
13 c = consumer('A')
14 c2 = consumer('B')
15 c.__next__()
16 c2.__next__() #唤醒yield
17 print("老子开始准备做包子啦!")
18 for i in range(10):
19 time.sleep(1)
20 print("做了1个包子,分两半!")
21 c.send(i)
22 c2.send(i) #唤醒yield并且传值
23
24 producer("shogou")
2.说明:
生成器,只有在调用时才会生成相应的数据。(只能用循环,不能像列表一样去切片))
只记住当前位置;
只有一个 .__next__方法。 (2.X版本中next())
二. 迭代器
可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型:list , tuple ,dict ,set ,str等;
一类是generator,包括生成器和带yield的generator function.
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable.
可以使用isinstance() 判断一个对象是否是Iterable对象:
>>>from collections import Iterable
>>>isinstance([], Iterable)
True
生成器不但可以作用于for循环,还可以被__next__()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
可以被__next__()函数调用并不断返回下一个值的对象称为迭代器:Iterator.(是迭代器就有__next__()方法)
>>>from collections import Iterator
>>>isinstance([], Iterator )
False
生成器都是Iterator对象,但list, dict ,str 虽然是Iterable,却不是Iterator。把list, dict ,str 等Iterable变成Iterator可以使用iter()函数:
a=[1,2,3]
type (a)
b = iter(a)
b.__next__()
小结:
Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算,Iterator甚至可以表示一个无限大的数据流,例如全体自然数。使用list是永远不可能存储全体自然数的 。