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

  

猜你喜欢

转载自www.cnblogs.com/Hexdecimal/p/9316944.html