zoukankan      html  css  js  c++  java
  • 生成器和迭代器

    一,迭代器(iterator)和可迭代对象(iterable)

    1.两者的介绍:

        迭代器:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stopiteration异常,以终止迭代(只能往前走不能后退)

      可迭代对象:实现了迭代器协议的对象(实现:对象内部定义一个_iter_()方法)

         注:字符串、列表、元组、字典、集合、文件对象这些都不是可迭代对象,只不过for循环调用了他们内部的_iter_方法,把他们变成了可迭代对象。

    例:可迭代对象的使用方法:
    a = [1,2,3]
    iter_a = a.__iter__()
    print(iter_a.__next__())
    print(iter_a.__next__())
    print(iter_a.__next__())
        注:
        print(next(iter_a)) = print(iter_a.__next__())
        一个调用python提供的内置函数,一个调用数据类型提供的方法
    
    例:用while去模拟for循环:
    a = [1,2,3,5]
    iter_a = a.__iter__()
    while True:
        try:
            print(iter_a.__next__())
        except StopIteration:
            break

    2.迭代器和可迭代对象的判断

        可以使用isinstance()判断

    >>> 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
    
    
    
    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False

        笔者自己画的图,他们之间的关系如图所示

                          无标题

    小结:

        凡是可作用于for循环的对象都是Iterable类型;

        凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

        集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

        Python的for循环本质上就是通过不断调用next()函数实现的.

    二、生成器

    1.什么是生成器:
        可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他的数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象。
    2.生成器分类:
        1):生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个据俄国中间,挂起函数的状态,以便下次从他离开的地方继续执行.
        2): 生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构造一个结果列表。

    3.生成器特点:
        1).获得返回值yield(类似函数return)
        2).保留函数的运行状态,下一次运行相当于执行__next()__方法
    4.生成器函数总结:
        1).语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值。
        2).自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环、sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用你它next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常
        3).挂起状态:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行

    #--------包子案例:商家做包子,客人吃包子
    import time
    def product_baozi():
         for i in range(100):
             yield '做好了包子%s'%i
             time.sleep(3)
    baozi = product_baozi()
    names = ['aaa','bbb','ccc','ddd']
    for name in names:
        s = baozi.__next__()
        time.sleep(1)
        print( s[3:],'已被%s吃了'%name)

    *附加:生成器只能遍历一次!

    示例:

    def test():
    for i in range(4):
    yield i
    n = test()
    n1 =(i for i in n)
    n2 =(i for i in n1)
    print(list(n2))
    输出结果:
    [0, 1, 2, 3]
    ******************
    def test():
    for i in range(4):
    yield i
    n = test()
    n1 =(i for i in n)
    n2 =(i for i in n1)
    print(list(n1))
    print(list(n2))
    输出结果:
    [0, 1, 2, 3]
    []

    5.生成器的send用法

    def test():
        print('start')
        num = yield 1
        yield 2,num
        yield 3
    a = test()
    test0 = a.__next__()
    test1 = a.send(24)      #send的作用相当于使生成器继续运行,并且传递的参数为yield的返回值 
    test2 = a.__next__()
    print(test0)
    print(test1)
    print(test2)

    6.生产者和消费者模型

        通过yield实现在单线程的情况下实现并发运算的效果

    import time
    def producer(name):
        while True:
            baozi = yield
            time.sleep(1)
            print('%s已制作完毕'%baozi)
            print('%s把%s吃了'%(name,baozi))
            print('-'*30)
    
    def consumption():
        People_eat1 = producer('Jiang')
        People_eat2 = producer('Feng')
        People_eat1.__next__()
        People_eat2.__next__()
        for i in range(10):
            if (i+1)//2 ==1:
                People_eat1.send('包子%s'%i)
            else:
                People_eat2.send('包子%s'%i)
    consumption()
  • 相关阅读:
    推荐:《TestDrive ASP.NET MVC》 节选与作者访谈
    30天敏捷结果(15):让自己处于宁静状态
    MDSF:如何使用GMF来做TOGAF建模工具
    强烈推荐:好书、好人、好谚语
    推荐:50个加强表单的jQuery插件
    101与金根回顾敏捷个人:(1)基于MBTI模型发现你的职业性格
    30天敏捷结果(19):你在为谁做事?
    30天敏捷生活(13):获得他人的反馈
    SourceForge.net上的新项目(2005/07/05)
    Open License,开源的许可生成器,实现你自己的许可管理器/应用
  • 原文地址:https://www.cnblogs.com/feng0919/p/10128901.html
Copyright © 2011-2022 走看看