• python迭代器和生成器


    迭代器

      首先说几个概念:

    1. 什么是可迭代对象(iterable)  :   顾名思义,可以返回一个迭代器的对象,也可以说能够在for循环中所使用的对象.如tuple,list,set等
    2. 什么是迭代器(iterator)         :   从一个集合序列中不断提取元素,直到没有元素可以返回,抛出异常.

     

        如何获取迭代器:

      通过可迭代对象的 __iter__方法来获取,

        

    1 #coding = utf-8
    2 lst = ["小明",["小李"],"小王","小刘"]  #lst是list类型,是可迭代对象
    3 it = lst.__iter__()    #it就是迭代器

      如何判断是否为可迭代对象.

      

    #coding = utf-8
    content = dir(list)  
    print(content)  #list中存在__iter__,是可迭代对象
    '''
    ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
    '''

      如何判断是迭代器还是可迭代对象.

      这里给出两种方法:

      (1) 通过dir()查看,同时存在__iter__和__next__方法的就是迭代器,只存在__iter__的就是可迭代对象.

    print("__iter__"in dir(list))
    print ("__next__"in dir(list))    #返回的是布尔值

      (2)通过python的collections

    from collections import iterable
    from collections import iterator
    
    print (isinstance(lst,iterable))
    print (isinstance(lst,iterator))
    print (isinstance(lt,iterable))
    print (isinstance(lt,iterator))

      迭代器的工作原理

      通过调用__next__函数,返回序列中下一个元素,直到取到最后一个抛出异常.StopIteration.

    #coding = utf-8
    lst = ["小明","小李","小王","小刘"]
    it = lst.__iter__()
    while 1:
            print(it.__next__())  #StopIteration

      迭代器的特点

      (1)只能返回下一个,不可逆向.

      (2)惰性机制,只有给予指令之后才会执行操作.

      (3)不占用内存.

       通过__next__方法模拟for循环.

    lst = ["小明","小李","小王","小刘"]
    it = lst.__iter__()
    while 1:
         try:
             print(it.__next__())
         except StopIteration:    #抛出异常退出
             break

     

    生成器

      生成器迭代器是较为容易混淆的两个概念.

      生成器: 返回的是一个迭代器对象的就是生成器 , 简单来说,加上yield的函数便构成了一个生成器.

      生成器的构造有以下几种方式:

        1,通过yield,普通的函数中包含yield就是生成器.

        2,通过生成器表达式

    #coding = utf-8    
    #通过添加yield
    def func():
        yield 2
    gen = func()
    print(gen.__next__())    #2
    #coding = utf-8
    #通过推导式
    gen = (i for i in range(0,3))
    print(gen.__next__())    #0
    print(gen.__next__())    #1
    print(gen.__next__())    #2

      在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 __next__() 时从当前位置继续运行。

      实际上next()send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做c.next() 和 c.send(None) 作用是一样的。

      例如

    #codiing = utf-8
    def func():
        yield 456
    a = func()  #获取迭代器对象
    print (a.__next__())    #456
    a = func()    #惰性机制
    print(a.send(none))    #456

      显而易见,两次打印结果相等.

     

     关于yield

      yield的作用和return相似,都具有有类似break特点,不同点是其中return是终止程序,而yield是等待下一次运行,分段进行函数.

    #coding = utf-8
    def func():
        return 1    #第一个return返回,第二个被终止 不再执行
        return 2    
    ret = func()    
    print(ret)    
    #coding = utf-8
    #1,2两个值都被返回
    # def func():
    #     yield 1    
    #     yield 2
    # gen = func()
    # print(gen.__next__())    #1
    # print(gen.__next__())    #2

     

     关于send()

      send()和__next__一样,都具有让生成器走向下一次的作用,但是send()具有向上一个yield传递值的作用,也正是由于这一特性,第一次执行生成器代码的时候,用__next__而不用send()

    #coding =utf-8
    def func():
        a = yield 1
        yield a
        yield 3
    gen = func()
    print(gen.__next__())
    print(gen.send(5))    #send里的值赋值给上一个yield 导致a = 5
    print(gen.send(gen))

       

     

  • 相关阅读:
    安装MySQL5.7.19 网上的文章参考 并做了部分修改
    从hadoop一路配置到spark
    java面试问题收集(2)
    JAVA的 IO NIO AIO笔记
    Shiro
    Spring注解使用注意点
    oracle RAC
    spark随笔
    Storm知识点笔记
    真机调试手机程序,电脑插上手机数据线虚拟机中的系统就死掉
  • 原文地址:https://www.cnblogs.com/cuiyuanzhang/p/9468057.html
Copyright © 2020-2023  润新知