zoukankan      html  css  js  c++  java
  • python 迭代器(二):迭代器基础(二)可迭代的对象与迭代器的对比

    可迭代的对象

    如果对象实现了能返回迭代器的 __iter__ 方法,那么对象就是可迭代的。
    序列都可以迭代;实现了 __getitem__ 方法,而且其参数是从零开始的索引,这种对象也可以迭代。
    >>> s = 'ABC'
    >>> it = iter(s)  #
    >>> while True:
    ...     try:
    ...         print(next(it))  #
    ...     except StopIteration:  #
    ...         del it  #
    ...         break  #
    ...
    A
    B
    C

    ❶ 使用可迭代的对象构建迭代器 it。
    ❷ 不断在迭代器上调用 next 函数,获取下一个字符。
    ❸ 如果没有字符了,迭代器会抛出 StopIteration 异常。
    ❹ 释放对 it 的引用,即废弃迭代器对象。
    ❺ 退出循环。

    StopIteration 异常表明迭代器到头了。Python 语言内部会处理 for循环和其他迭代上下文(如列表推导、元组拆包,等等)中的StopIteration 异常

    标准的迭代器接口有两个方法

    __next__
      返回下一个可用的元素,如果没有元素了,抛出 StopIteration异常。

    __iter__
      返回 self,以便在应该使用可迭代对象的地方使用迭代器,例如在 for 循环中。

    这个接口在 collections.abc.Iterator 抽象基类中制定。这个类定义了 __next__ 抽象方法,而且继承自 Iterable 类;__iter__ 抽象方法则在 Iterable 类中定义。

    图 14-1:Iterable 和 Iterator 抽象基类。以斜体显示的是抽象方法。具体的 Iterable.__iter__ 方法应该返回一个 Iterator 实例。

    具体的 Iterator 类必须实现 __next__ 方法。Iterator.__iter__ 方法直接返回实例本身

    示例 14-1 sentence.py:把句子划分为单词序列

    import re
    import reprlib
    
    RE_WORD = re.compile('w+')
    
    class Sentence:
    
        def __init__(self, text):
            self.text = text
            self.words = RE_WORD.findall(text)   ➊
        def __getitem__(self, index):
            return self.words[index]   ➋
        def __len__(self):   ➌
            return len(self.words)
    
        def __repr__(self):
            return 'Sentence(%s)' % reprlib.repr(self.text)   ➍

    ❶ re.findall 函数返回一个字符串列表,里面的元素是正则表达式的全部非重叠匹配。
    ❷ self.words 中保存的是 .findall 函数返回的结果,因此直接返回指定索引位上的单词。
    ❸ 为了完善序列协议,我们实现了 __len__ 方法;不过,为了让对象可以迭代,没必要实现这个方法。

    ❹ reprlib.repr 这个实用函数用于生成大型数据结构的简略字符串表示形式。

    再看示例 14-1 中定义的 Sentence 类,在 Python 控制台中能清楚地看出如何使用 iter(...) 函数构建迭代器,以及如何使用 next(...) 函数使用迭代器:

    >>> s3 = Sentence('Pig and Pepper')  #
    >>> it = iter(s3)  #
    >>> it  # doctest: +ELLIPSIS
    <iterator object at 0x...>
    >>> next(it)  #
    'Pig'
    >>> next(it)
    'and'
    >>> next(it)
    'Pepper'
    >>> next(it)  #
    Traceback (most recent call last):
      ...
    StopIteration
    >>> list(it)  #
    []
    >>> list(iter(s3))  #
    ['Pig', 'and', 'Pepper']

    ❶ 创建一个 Sentence 实例 s3,包含 3 个单词。
    ❷ 从 s3 中获取迭代器。
    ❸ 调用 next(it),获取下一个单词。
    ❹ 没有单词了,因此迭代器抛出 StopIteration 异常。
    ❺ 到头后,迭代器没用了。
    ❻ 如果想再次迭代,要重新构建迭代器。

    因为迭代器只需 __next__ 和 __iter__ 两个方法,所以除了调用next() 方法,以及捕获 StopIteration 异常之外,没有办法检查是否还有遗留的元素。
    此外,也没有办法“还原”迭代器。如果想再次迭代,那就要调用 iter(...),传入之前构建迭代器的可迭代对象。
    传入迭代器本身没用,因为前面说过 Iterator.__iter__ 方法的实现方式是返回实例本身,所以传入迭代器无法还原已经耗尽的迭代器。

    迭代器

    迭代器是这样的对象:实现了无参数的 __next__ 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常。
    Python 中的迭代器还实现了 __iter__ 方法,因此迭代器也可以迭代。因为内置的 iter(...) 函数会对序列做特殊处理,所以第 1 版Sentence 类可以迭代。





  • 相关阅读:
    Mac Terminal菜鸟篇之使用unrar解压rar文件
    Android开发之帐户管理
    Android API之android.view.View.MeasureSpec
    Android API之onLayout, onMeasure
    Android API之android.os.AsyncTask
    Android开发之Shortcuts, LiveFolder, Widget
    Android开发之短信
    Android系统示例分析之AndroidBeamDemo
    Android开发之定位系统
    Android系统示例之ActionBarCompat
  • 原文地址:https://www.cnblogs.com/qiu-hua/p/12964824.html
Copyright © 2011-2022 走看看