Python iterator:关于Python的迭代器

可迭代对象(Iterable)

class Iterable(metaclass=ABCMeta):

    __slots__ = ()

    @abstractmethod
    def __iter__(self):
        while False:
            yield None

    @classmethod
    def __subclasshook__(cls, C):
        if cls is Iterable:
            return _check_methods(C, "__iter__")
        return NotImplemented

可迭代对象就是可以直接作用于for循环的对象。用于for循环 的数据类型一般分为两种:

  • 集合数据类型,如list、tuple、dict、set、string……
  • generator,包括生成器和带yield的generator function

Python的内建函数__iter__()__next__()

list、tuple、dict、set、string 在使用for … in … 的时候,其实都是在使用其定义的__iter__() 获得迭代器(iterator ) ,然后通过 iterator 的__next__()遍历整个集合。 list.__iter__()list. __next__() 也可以写成iter(list)next(list), list 在这里是集合对象。

for … in … 循环的本质就是先通过iter()函数获得一个迭代器,然后对获得迭代器不断不得调用next()方法来取得下一个值,并赋值给item当遇到StopIteration的异常后结束循环。

通过list的例子说明

我们用继承的方法把迭代器改为我们自己构建的迭代器(ListIterator),在 ListIterator 中实现__next__()方法。抛出 StopIteration ,作为for循环的停止信号。

class SimulationList(list):
    def __iter__(self):
        return ListIterator(self)


class ListIterator:
    def __init__(self, values: SimulationList):
        self.values = values
        self.i = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.i == len(self.values):  # 这里的 i 代表被分配到内存中的值,这条语句类比 list存储在内存中的值遍历结束
            raise StopIteration  # 抛出 StopIteration 是为了让for ... in ...处理,结束遍历
        self.i += 1
        return self.values[self.i - 1]

    def __len__(self):
        return len(self.values)


l = SimulationList([1, 2, 3, 4])
print(type(l))
for i in iter(l):
    print(i)
for i in l:
    print(i)

结果

<class ‘__main__.SimulationList’>
1
2
3
4
1
2
3
4

所以对于for … in …来说,需要传入的是一个可迭代的对象,或是一个迭代器,它可以根据可迭代对象生成迭代器实例,再调用迭代器的next方法实现遍历。

l = [1, 2, 3, 4]
iterator = l.__iter__()
print(list(iterator))
print(list(iterator))

#  [1, 2, 3, 4]
#  []

迭代器使用完成后,会返回StopIteration ,即已经不可逆的遍历了集合,如果需要重新遍历,则需要重新生成Iterator。

事实上range也是一个可迭代的类,所以可以用for,
issubclass(range, Iterable) 为True





除非注明,否则均为一叶呼呼原创文章,转载必须以链接形式标明本文链接

本文链接:http://www.yiyehu.tech/archives/2020/04/03/python-iterator

发表评论

电子邮件地址不会被公开。 必填项已用*标注