zoukankan      html  css  js  c++  java
  • Python的迭代器

    迭代器

    1、什么是迭代器?

      迭代器指的是迭代取值的工具,迭代是一个重复的过程,每一次重复都是基于上一次的结果单纯的重复不是迭代(更新迭代)
    每一次对过程的重复称为一次“迭代,而每一次迭代得到的结果会作为下一次迭代的初始值。
    # 举例:单纯的重复,这不是迭代
    # while True:
    #     name = input(">>")
    
    # 举例:这是迭代,每一次重复都是基于上一次的结果。爸爸-->儿子-->孙子,下述while循环才是一个迭代过程
    # count = 0
    # while count<5:
    #     print(count)
    #     count += 1

    2、为何要有迭代器? 

    迭代器是用来迭代取值的工具,而涉及到把多个值循环取出来的类型有列表、字符串、元组、字典、集合、文件
    # 对于list,tuple,string
    l = ['lsj','tianjing']
    i = 0
    while i < len(l):
        print(l[i])
        i += 1
    # 上述迭代取值的方式只适用于有索引的数据类型例如:列表、字符串、元组。
    # 没有索引的数据类型:字典、集合、打开的文件,如果我想迭代取值该怎么办?这就是基于索引迭代取值的局限性。
    # 为了解决基于索引迭代器取值的局限性。python必须提供一种能够不依赖于索引的取值方式,这就是迭代器

    3、可迭代对象

      可迭代对象(iterable):但凡内置有__iter__方法的都称之为可迭代的对象。

    # 如下所示:字符串、列表、元组、字典、集合、打开的文件都有内置__iter__方法都是可迭代对象
    # 定义一个空字符串
    s1=''
    s1.__iter__()
    # 定义一个列表
    l=[]
    l.__iter__()
    # 定义一个元组
    t=()
    t.__iter__()
    # 定义一个字典
    d={'a':1}
    d.__iter__()
    # 定义一个集合
    set1={1,2,3}
    set1.__iter__()
    # 打开一个文件
    with open('a.txt',mode="w") as f:
        f.__iter__()
        # pass
    # 不依赖于索引的取值方案,所以要用到迭代器
    # 调用可迭代对象下的__iter__方法会将其转换成迭代器对象,转换成功后就不依赖于索引取值了
    d = {"a":1,"b":2,"c":3}
    res = d.__iter__()
    print(res)
    # 不依赖于索引的取值方案,所以要用到迭代器
    # 调用可迭代对象下的__iter__方法会将其转换成迭代器对象
    d = {"a":1,"b":2,"c":3}
    d_iterator= d.__iter__()  # 此时的res就是可迭代器对象
    # print(d_iterator)
    
    # d_iterator.__next__() # 取值
    # print(d_iterator.__next__())  # 得到字典的key  a
    # print(d_iterator.__next__())  # 得到字典的key  b
    # print(d_iterator.__next__())  # 得到字典的key  c
    #
    # print(d_iterator.__next__())  # 字典中有三个值,再去一次会抛出异常:StopIteration,表示迭代器没有值可取了
    
    # 把该迭代器想象一只老母鸡,这个老母鸡是有寿命的,这只老母鸡一生中只能下200个鸡蛋,下一个身体机能也有损耗,当下到最后一个时候,遇到StopIteration,会死掉
    # 使用while循环代表上面四个取值,如下:
    while True:
        print(d_iterator.__next__())
    
    """结果如下:
    a
    b
    c
    StopIteration
    """
    # 如何解决上面的异常?使用try...except
    while True:
        try:
            print(d_iterator.__next__())
        except StopIteration:
            break
    """运行结果如下:
    a
    b
    c
    """
    # 对同一迭代器取值,在取干净的情况下再一次取值,就会取不到。
    print("====================================")
    while True:
    try:
    print(d_iterator.__next__())
    except StopIteration:
    break
    # 运行结果:为空
    # 如果我想在去一便呢?需要再次造一次迭代器
    d_iterator = d.__iter__()
    while True:
        try:
            print(d_iterator.__next__())
        except StopIteration:
            break
    # 运行结果如下:
    """
    a
    b
    c
    """
    # 迭代器与for循环工作原理
    # 使用while 循环体现迭代器功能,比较麻烦,有无更简单的方案,那就是for循环
    
    # 3、可迭代对象与迭代器对象详解
    # 3.1、可迭代对象("可以转换成迭代器的对象"):内置有__iter__方法对象
    #         可迭代对象.__iter__():得到迭代器对象
    #         可迭代对象例如:字符串、元组、列表、集合、字典
    # 3.2、迭代器对象:内置有__next__方法并且内置有__iter__方法的对象
    #           迭代器对象.__next__():得到迭代器的下一个值
    #           迭代器对象.__iter__():得到迭代器的本身,(调用和没调用一样)
    #           迭代器对象例如:只有文件时迭代器对象
    # 总结:可迭代对象不是可迭代器对象,但是迭代器对象是可迭代的对象
    
    
    # dic = {"a":1,"b":2,"c":3}
    # dic_iterator = dic.__iter__()
    #
    # print(dic_iterator is dic_iterator.__iter__())  # True,也就是说调用迭代器的__iter__()跟没调一样
    
    
    # for循环会调用iter方法
    # for x in 迭代器对象.__iter__(): 
    #     pass
    
    # 定义一个字典
    dic = {"a":1,"b":2,"c":3}
    # 在没有使用迭代器的时候直接使用for寻魂,简单粗暴
    for k in dic:
        print(k)
    """
    a
    b
    c
    """
    
    # 使用迭代器会如下所示:
    dic_iterator = dic.__iter__()
    while True:
        try:
            print(dic_iterator.__next__())
        except StopIteration:
            break
    """
    a
    b
    c
    """
    # 总结:for循环的工作原理
    # 1、d.__iter__()得到一个迭代器对象
    # 2、迭代器对象.__next__()拿到一个返回值,然后该返回值赋值给k
    # 3、循环往复步骤2,直到抛出异常StopIteration的异常,for循环会不捉异常后结束循环
    with open("test018_07a.txt",mode='rt',encoding='utf-8') as f:
        # for line in f:  # f.__iter__() 迭代器对象调用__iter__(),结果还是它本身
        for line in f.__iter__():
            print(line)
    """f = f.__iter__(),运行结果如下
    aaa
    
    bbb
    
    ccc
    
    """

     迭代器的优缺点:

      基于索引的迭代取值,所有迭代的状态都保存在了索引中,而基于迭代器实现迭代的方式不在依赖索引,所有迭代的状态就保存在迭代器中。

    优点:

      1、为序列和非序列类型提供一种统一的迭代取值方式。

      2、惰性计算:懒汉式计算,只有在需要数据的时候才去调用next来计算出一个值,就迭代器本身而言,同一时刻在内存中之哟一个值。

    缺点:

      1、除非取尽,否则无法获取迭代器的长度。

      2、只能取下一个值,不能回到开始,更像是‘一次性的’,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停留在某个位置,等待下一次调用next;若是要再次迭代同个对象,你只能重新调用iter方法去创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值

    验证range()是否为可迭代对象?

    >>> range(1,3).__iter__
    <method-wrapper '__iter__' of range object at 0x000001C9D9C90810>
    >>> range(1,3).__next__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'range' object has no attribute '__next__'
    # 验证字典取keys()是否为可迭代对象?
    >>> {"a":1}.keys()
    dict_keys(['a'])
    >>> {"a":1}.keys().__iter__
    <method-wrapper '__iter__' of dict_keys object at 0x000001C9D9C90820>
    >>> {"a":1}.keys().__next__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'dict_keys' object has no attribute '__next__'

    4、如何使用迭代器?

     

     

     

  • 相关阅读:
    搭建es7.5的配置文件
    kafka的暂停消费和重新开始消费问题
    hive sparksession查询只显示defalt库问题
    flink widow&window funcion&水印
    flink支持的数据类型讲解(可序列化) 和 内置累加器的运用
    mysql tar安装模式
    Permission denied: user=root, access=WRITE, inode="/":hdfs:supergroup:drwxr-xr-x
    错误Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FSDataInputStream排查思路
    SPSS非参数检验
    SPSS回归分析
  • 原文地址:https://www.cnblogs.com/liunaixu/p/12635374.html
Copyright © 2011-2022 走看看