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

    一、迭代器 Iterator
     
    1、可迭代对象:str、list、tuple、set、dict、文件句柄,range
                            __iter__() 这个方法导致了数据类型的可迭代
    检测一个对象是否可迭代:
    from collections import Iterable
    print(isinstance('aaa',Iterable))
    print(isinstance(123,Iterable))
    输出 True  False

    2、可迭代协议:只要包含了__iter__()方法的数据类型就是可迭代的

                            这是数据类型和python解释器定下来的协议
    dir(对象),可以查看此类型的对象所有的方法
    print(dir((1,3))
    输出:列表
    ['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']
     
    3、迭代器 iterator
      就是实现了能从其中一个一个的取出值来
      迭代器 不关心值的索引状态  (所以for循环才能循环字典,集合等)
            for循环,在遍历之前,先调用对象的__iter__方法,将其转换成1个迭代器,然后用迭代器协议去实现循环访问
    lst_iterator = [1,2,3].__iter__()       #lst_iterator 就是一个迭代器(通过可迭代对象,用__iter__()方法,获得)
    print(lst_iterator)
    输出
    <list_iterator object at 0x00000203948C8710>  

        #天生就是迭代器的:比如文件句柄

        #后天生成迭代器的:比如 可迭代对象.__iter__() 
     
     
    列表的迭代器跟 列表比起来,有哪些新的方法:
    print(set(dir(lst_iterator))-set(dir([1,2,3])))
    输出:
    {'__next__',                       #一个一个取值
     '__length_hint__',                #获取迭代器中元素的长度
     '__setstate__'}                     #根据索引值指定从哪里开始迭代
     
    4、迭代器协议:
    迭代器中拥有__next__ 和 __iter__ 方法
     
    检测是否是迭代器:
    from collections import Iterator
    lst_iterator = [1,2,3].__iter__()  
    print(isinstance(lst_iterator,Iterator))
    print(isinstance([1,2,3],Iterator))
    输出True  False

    在python中,学过的所有可以被for循环的 基本数据类型 都是可迭代的,而不是迭代器

    文件句柄是 迭代器
    range是可迭代对象,但不是迭代器,包含__iter__,没有__next__
    for 可以是一个可迭代对象,也可以是一个迭代器
     
    迭代器和可迭代对象之间的关系:
        #迭代器包含可迭代对象,
        #迭代器 = 可迭代对象.__iter__()
     
    5、迭代器存在的本质是什么:
        #1、能够对python中的基本数据类型进行统一的遍历,不需要关心每一个值分别是什么
        #2、可以节省内存    ——惰性运算
      
    用__next__实现一个for循环
    lst_iterator = [1,2,3].__iter__()
    while True:
        try:
            print(lst_iterator.__next__())
        except StopIteration:                  ##接收到异常错误,就怎么怎么样
            break
    输出:1  2  3

    二、生成器 Generator

     
    1、生成器
        是自己写出来的,就是迭代器
            # 生成器函数
                  yield / yield from
                  yield语句,一次返回一个结果,在每个结果中间,挂起函数状态,以便下次从它离开的地方继续执行。
    def generator_func():          ###生成器函数
        print(123)
        yield 'aaa'
        print(465)
        yield 'bbb'
    g = generator_func()          ###生成一个迭代器g
    print(g)       输出:<generator object generator_func at 0x00000226D0EC0EB8>
    print(g.__next__())          输出:123 aaa
    print(g.__next__())          输出:456 bbb

    #带yield关键字的函数,就是生成器函数

    #生成器函数,在调用的时候,只返回一个生成器,不执行生成器函数中的内容
     
    2、从生成器中取值:
        #1、__next__  有几个yield 就可以取几次
        #2、for  循环取值,正常取  for i in g:
        #3、其他数据类型强制转换, list (g)  返回1个列表,里面包含生成器的所有内容
                #注意:调用生成器函数时,要先获取生成器,再进行next取值
                            生成器中的内容,只能取一个,且按顺序取值,没有回头路,取完为止
     
    3、举例
    def generator_func():
        yield 123
        yield 456

    def get_clothing():
        for cloth in range(1,500):
            yield "第%s件衣服" % cloth
    g = get_clothing()
    for i in range(50):              #一下取出50件衣服(通过设定执行多少次yield来进行)
        print(g.__next__())         
    for i in g:                          #取出前多少件衣服 (通过判断yield出来的值,来判断是否继续进行)
        print(i)
        if i =="第100件衣服":
            break

    def func1()
        for i in [1,2,3,]:
            yield i
        for j in 'ABC':
            yield j
     
    def func2()
        yield from [1,2,3]       ##只有python3里有 yield from
        yield from 'ABC'

    4、对文件输入的监控

    import time
    def  tail():
        with open('tmp') as f:
            f.seek(0,2)                 #光标移动到最后
            while True:
                line = f.readline()
                if not line:
                    time.sleep(0.5)
                    continue
                yield line
    g = tail()
    for i in g:
        print(i,end="")
  • 相关阅读:
    C#的类,构造函数以及Array阵列的数据填充与绑定
    子菜单显示了,就不想隐藏了
    获取DataTable选择第一行某一列值
    两个dropDownList和一个GridView的选择与显示
    127.0.0.1SQLEXPRESS连接异常
    Unrecognized attribute 'targetFramework'. Note that attribute names are case-sensitive.
    The system cannot find the file specified
    Handler "BlockViewHandler" has a bad module "ManagedPipelineHandler" in its module list
    The Web server is configured to not list the contents of this directory.
    分布式监控系统Zabbix-图形集中展示插件Graphtree安装笔记
  • 原文地址:https://www.cnblogs.com/tangjianyu/p/7475163.html
Copyright © 2011-2022 走看看