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

    迭代器协议

    对象必须提供一个 next() 方法,执行该方法要么迭代下一项,要么就引起一个 StopIteration异常以终止迭代(只能往后不能往前)—— 迭代器协议

    协议是一种约定,可迭代对象实现了迭代器协议(for、sum、min、max 等使用迭代器协议访问对象)

    可迭代对象(iterable)

    实现了迭代器协议的对象,就是可迭代对象。如何实现迭代器协议:对象内部定义 __iter__() 方法。

    可作用于 for 循环的对象统称为可迭代对象,能作用于 for 循环的数据类型有以下几种:

    • 集合数据类型:liststrtupledicttuple
    • 生成器 generator:包括生成器函数和带 yield 关键字的生成器对象

    可以用 isinstance() 判断一个对象是否是可迭代对象:

    from collections import Iterable
    	
    isinstance([], Iterable)			# True
    isinstance('123', Iterable)			# True
    isinstance(123, Iterable)			#  False
    

    可迭代对象是可迭代的(即能被 for 循环),但不是迭代器,因为 next() 函数无法调用它们:

    next([1, 2, 3])
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-38-4a6488f07b8e> in <module>()
    ----> 1 next([1, 2, 3])
    
    TypeError: 'list' object is not an iterator		# list 对象不是一个迭代器
    

    但是可以用 iter() 函数将其转换为迭代器:

    l = [1, 2, 3]
    ret = iter(l)		# 转换为迭代器
    next(ret)			# 调用 next() 函数
    
    ------------------------
    1
    

    迭代器(iterator)

    可以被next()函数调用并不断返回下一个值的对象称为迭代器Iterator

    迭代器对象从集合第一个元素开始访问,直到所有元素被访问完才算结束,只能往前不能往后。

    使用isinstance()判断一个对象是否是Iterator对象:

    from collections import Iterator
    isinstance([], Iterator)        					# list 不是迭代器对象,False
    isinstance(iter([1, 2, 3]), Iterator)   			# 用 iter() 将 list 转换为迭代器,True
    isinstance((x for x in range(10)), Iterator)   		# 生成器是迭代器对象
    

    迭代器惰性机制

    迭代器表示的是一个数据流,可以调用 next() 函数不断返回下一个数据,直至没有数据抛出 StopIteration。可以说它是一个有序序列,但我们不知道序列长度,只能通过 next() 函数实现按需计算下一个数据,所有它是惰性的,只有在需要时才计算返回下一个数据。


    为什么要有迭代器

    对于有序序列类型,使用索引以及 while 循环也难遍历所有元素,但是对于无序序列类型(字典、集合)就会束手无策。


    for 循环机制

    for 循环是基于迭代器协议提供了一个统一的可遍历所有对象的方法,调用对象的 __iter__() 方法将其转换为一个迭代器,再调用 __next__() 不断取出序列中元素。相比较迭代器而已,for 循环还完成了 StopIteration 的异常工作。

    这样一来,只要是序列,都可以通过 for 循环遍历,不管是有序还是无序序列类型。


    优缺点

    优点:

    • 提供一种不依赖于索引的迭代方式
    • 惰性计算,节省内存(每次取值,才会加载)

    缺点:

    • 无法获取长度,next() 完毕才知道
    • 一次性,只能往前,不能往后

    自定义类为迭代器

    要想将自定义的类实现为一个迭代器,需要在类中实现 __iter__()__next__()方法:

    • __iter__() 方法:返回迭代器对象本身
    • __next__() 方法:返回容器中下一个元素,当超出边界时触发 StopIteration 异常终止迭代器
    class Foo(object):
        def __init__(self,step):
            self.step = step
            
        def __next__(self):
            if self.step == 0:
                raise StopIteration
            self.step -= 1
            return self.step
        
        def __iter__(self):
            return self
    f = Foo(6)
    for i in f:
        print(i)
    
    5
    4
    3
    2
    1
    0
    

    总结

    • 可以 for 循环的对象都是可迭代类型
    • 可以作用于 next() 函数的对象都是迭代器类型,它表示一个惰性计算的序列
    • listdictstr 等都是可迭代的,但不是迭代器类型,因为没有 next() 方法,可以用 iter() 函数将其转换为迭代器
    • Python 的 for 循环机制其实质是不断调用 next() 函数实现的,但是它超出边界不会触发 StopIteration
    • for 循环一次将所有数取出,迭代器一次只取一个
  • 相关阅读:
    wsl手动启动特定的子系统
    winserver安装wsl
    wsl子系统下载地址-补充centos7地址
    wsl (1)-含wsl子系统各启动命令
    win10系统版本说明
    zenith 以及海康 rtsp流
    shinobi (4)
    ffmpeg
    CF993A Two Squares 几何 第二道 暴力或判断条件(*)
    CF994B Knights of a Polygonal Table 第一道 贪心 set/multiset的用法
  • 原文地址:https://www.cnblogs.com/midworld/p/10471607.html
Copyright © 2011-2022 走看看