Python中的迭代器

以下是Python文档中对于迭代器类型的描述

Python有一个在容器上进行迭代的概念。其实现需要两个方法来支持;这让用户自己定义的类也可以支持迭代。序列类型都支持迭代方法。

容器对象需要提供一个方法来提供对于迭代的支持:

container.__iter__():这个方法返回一个迭代器对象。这个对象必须支持后面所描述的迭代器协议。如果一个容器要支持不同类型的迭代,则可以提供额外的方法来专门为这些迭代类型请求相应的迭代器。(对象支持多种迭代形式的一个例子就是树数据结构中对广度优先和深度优先遍历的支持)。这个方法对应于Python/C API中Python对象类型结构体中的tp_iter字段。

迭代器对象自身必须具有如下两个方法,这两个方法一起就构成了迭代器协议:

iterator.__iter__()

返回迭代器对象自身。这是为了让容器和迭代器都能支持for和in语句。这个方法对应于Python/C API中Python对象类型结构体中的tp_iter字段。

iterator.__next__()

返回容器中的下一个元素。如果没有更多的元素了,就会抛出StopIteration异常。这个方法对应于Python/C API中Python对象类型结构体中的tp_iternext字段。

Python定义了几种迭代器对象来支持对常规和特定序列类型、字典和其它特殊类型的迭代。特定类型主要地,就是实现了迭代器协议而已。

一旦迭代器的__next__()方法抛出了StopIteration异常,随后的调用中也必须这样做。不遵守此种行为的情况被视为迭代器已损坏。

以上是文档中对迭代器类型相关的介绍,其中的核心就是迭代器对象——也就是实现了迭代器协议的对象。为此我们先根据文档中的说明定义自己的一个迭代器:

class SimpleIterator:
    def __init__(self, max_index, position=0):
        self._position = position
        self._max = max_index

    def __iter__(self):
        return self

    def __next__(self):
        current_position = self._position
        if current_position <= self._max:
            self._position += 1
            return current_position
        else:
            raise StopIteration


if __name__ == '__main__':
    simple_iterator = SimpleIterator(100)
    for item in simple_iterator:
        print(item)

这是一个非常简单的迭代器,在其上迭代可以依次访问从初始化的position到max_index的所有整型数,并且是个闭区间(我在条件中使用了<=)。

现在我们实现了迭代器,如果想要让容器支持迭代器协议,按照上面文档的说法,就应该在一个容器内部定义一个__iter__()方法,并且要求其返回一个迭代器对象,我写了一个简单的支持迭代的容器类,它可以支持正序和反序迭代容器中的内容:

class ReverseIterator:
    def __init__(self, seq=[]):
        self._seq = seq
        self._current_index = len(self._seq) - 1

    def __iter__(self):
        return self

    def __next__(self):
        if self._current_index < 0:
            raise StopIteration
        use_index = self._current_index
        self._current_index -= 1
        return self._seq[use_index]


class SimpleContainer:
    def __init__(self, seq=[], reverse=False):
        self._seq = seq
        self._reverse = reverse

    def __iter__(self):
        if not self._reverse:
            return iter(self._seq)
        else:
            return ReverseIterator(self._seq)


if __name__ == '__main__':
    print("reverse=False")
    simple_container = SimpleContainer([1, 2, 3], reverse=False)
    for item in simple_container:
        print(item)

    print("reverse=True")
    simple_container = SimpleContainer([1, 2, 3], reverse=True)
    for item in simple_container:
        print(item)

这里面,我使用了iter内置函数用来获取list类型的迭代器,用来支持默认的正序迭代;为了支持反序迭代,我自己实现了一个迭代器,根据容器的创建参数,容器的__iter__()方法会返回不同类型的迭代器,以支持不同类型的迭代。

最后,几点总结:

  • __iter__()方法总是返回迭代器对象;
  • __next__()方法需要在迭代器中返回下一个值;
  • 迭代器对象中的__iter__()方法主要目的是为了让迭代器对象自身也支持for和in语句;
  • 可以根据容器设置的条件,指定使用不同类型的迭代器;
  • 要避免在迭代器协议实现的过程中复制底层容器对象(比如通过list[::-1]表达式来获取一个反序的新列表),防止内存资源浪费;

以上。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python迭代器具有以下特性: 1. 迭代器是一种对象,实现了迭代器接口(Iterator Interface),即包含`__iter__()`和`__next__()`方法。其,`__iter__()`方法返回迭代器对象本身,`__next__()`方法返回容器的下一个元素。 2. 迭代器可以用于遍历容器的元素,通过`for`循环或`list()`等内置函数进行遍历。容器必须实现`__iter__()`方法来返回迭代器对象。 3. 迭代器是惰性的,即只在需要时才生成下一个元素,节省了内存空间。每次调用`__next__()`方法时,迭代器会返回容器的下一个元素,直到遍历完所有元素,抛出`StopIteration`异常。 4. 迭代器可以在迭代过程动态修改容器的内容,因为它是实时生成元素的。但是,对于已经遍历过的元素,不能再次访问,需要重新创建迭代器。 5. 迭代器可以作为函数的返回值,实现惰性计算的效果。通过生成器函数或使用`yield`关键字,可以方便地创建迭代器。 6. 迭代器可以通过判断一个类是否实现了`collections.abc.Iterable`抽象基类来确定该类是否支持迭代器功能。 总结来说,迭代器是一种用于遍历容器元素的对象,具有惰性生成、动态修改和作为函数返回值等特性,可以方便地实现迭代功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Python语言特性:迭代器](https://blog.csdn.net/u014291956/article/details/87546697)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值