zoukankan      html  css  js  c++  java
  • 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
    

      

  • 相关阅读:
    Asp.Net 构架(Http Handler 介绍) Part.2<转>
    大数据插入<转>
    网站开发技巧参考大全<转>
    qq校友好东西
    SQL2005存储过程解密 <转>
    用Lucene.net对数据库建立索引及搜索<转>
    用SharpDevelop3调试ASP.NET的方法
    【转】卢彦的利用xml实现通用web报表打印
    张仰彪第二排序法 <转>
    依赖注入那些事儿 <转>
  • 原文地址:https://www.cnblogs.com/Hexdecimal/p/9316944.html
Copyright © 2011-2022 走看看