Python入门学习笔记04(生成器与迭代器)
生成器
列表生成式,根据一个简单规则生成对应列表,将列表生成式的[]替换为()即变成一个简单的生成器。
list1 = [i*2 for i in range(10)] generator1 = (i*2 for i in range(10))
上面的generator1便是一个简单的生成器。生成器是一组序列化的数据(并没有实际生成,而是在调用next的时候根据生成器的规则获取当序列的下一个,
因此生成器效率比列表等数据类型要高,节省内存),它只能通过next获取到一个值,既不能回溯,也不能跳过。
创建一个斐波那契数列生成器:
#构造一个斐波那契数列的生成器
def Fib(max):
a,b = 0,1
for i in range(max):
#yield的作用是保存现场,中断并返回生成器对象,可用于实现伪并行
#下一次next从yield处继续
yield b
# 下面的这一句代码等价于 t = (b,a+b)
# a,b = t[0],t[1]
a,b = b,a+b
#生成器的返回值可在生成器越界时抛出的错误StopIteration中获取
return "越界"
generator2 = Fib(10)
#由于生成器的特性,我们无法得知当前生成器得到的是序列的第几个值,所以有越界的可能性,
# 只能通过捕获StopIteration异常来得知生成器序列已结束
try:
while True:
print(next(generator2))
except StopIteration as e:
print(e.value)
输出
1 1 2 3 5 8 13 21 34 55 越界
生成器除了用yield返回之外其他与函数完全相同,也可以有返回值,但是生成器的返回值通过越界异常捕捉
使用yield返回是生成器的特征,yield的作用是返回当前值,并保存状态,当下次调用到next的时候生成器会从yield进入。
yield同时也可以用来进行赋值,这种情况下外部调用send(x)的时候便会将x传递给yield。
send的作用与next类似,就是多了一个传递值的作用。
使用yield实现一个简单的生产者消费者模型
import time def Customer(name): print("[%s]发出订单" %name) #调用send的时候会给yield赋值,同时执行next while True: dev = yield print("[%s]拿到了[%s]" %(name,dev)) def Factory(max): customer1 = Customer("装机店") customer2 = Customer("挖矿工厂") customer1.__next__() customer2.__next__() print("生产线准备就绪") for i in range(max): print("生产了两块主板") customer1.send("产品1") customer2.send("产品2") customer2.send("产品X") time.sleep(1) Factory(5)
输出
[装机店]发出订单 [挖矿工厂]发出订单 生产线准备就绪 生产了两块主板 [装机店]拿到了[产品1] [挖矿工厂]拿到了[产品2] [挖矿工厂]拿到了[产品X] 生产了两块主板 [装机店]拿到了[产品1] [挖矿工厂]拿到了[产品2] [挖矿工厂]拿到了[产品X] 生产了两块主板 [装机店]拿到了[产品1] [挖矿工厂]拿到了[产品2] [挖矿工厂]拿到了[产品X] 生产了两块主板 [装机店]拿到了[产品1] [挖矿工厂]拿到了[产品2] [挖矿工厂]拿到了[产品X] 生产了两块主板 [装机店]拿到了[产品1] [挖矿工厂]拿到了[产品2] [挖矿工厂]拿到了[产品X]
迭代器
迭代数据包括列表、字符串、数据字典、生成器等所有由序列化数据构成的数据结构,可以使用在for中表示范围的数据类型都是迭代数据。
迭代器是能够使用next来获取值的迭代数据,比如生成器。
lter()函数可以将一个迭代数据转化为一个迭代器
instance可以用来判断一个数据是否是迭代数据或迭代器
from collections.abc import Iterable from collections.abc import Iterator #Iterable可迭代数据,即可以用于for循环的数据,包括列表、字典、元组,集合和生成器数据 #Iterator迭代器,可以通过next获取下一个值的迭代数据 list1 = [x*x for x in range(10)] generator1 = (x*x for x in range(10)) print(isinstance(list1,Iterator)) print(isinstance(generator1,Iterator)) print(isinstance(list1,Iterable)) print(isinstance(generator1,Iterable)) #通过iter()函数可以将一个可迭代数据变成一个迭代器 dict1 = {1:"abc",100:"hello",-10:"bye"} #直接转换数据字典为迭代器使用的是key iter1 = iter(dict1) print(iter1.__next__()) print(iter1.__next__()) #将数据字典转换为元组列表再获取value进行转换 iter2 = iter(dict1.items()) print(iter2.__next__()[1])
输出
False True True True 1 100 abc