迭代器是可以迭代的对象。在本教程中,您将了解迭代器的工作原理以及如何使用 iternext 方法构建自己的迭代器。

Python 中的迭代器

迭代器在 Python 中无处不在。它们在for循环、理解、生成器等中优雅地实现,但隐藏在显眼的地方。
Python 中的迭代器只是一个可以迭代的对象。一个将返回数据的对象,一次一个元素。
从技术上讲,一个 Python迭代器对象必须实现两个特殊的方法,iter()和next(),统称为迭代器协议
如果我们可以从中获取迭代器,则该对象称为可迭代对象。Python 中的大多数内置容器,如:listtuplestring等都是可迭代的。
该iter()函数(依次调用该iter()方法)从它们返回一个迭代器。


通过迭代器迭代

我们使用该next()函数手动迭代迭代器的所有项目。当我们到达结束并且没有更多数据要返回时,它将引发StopIteration异常。下面是一个例子。

define a list mylist = [4, 7, 0, 3] # get an iterator using iter() myiter = iter(mylist) # iterate through it using next() # Output: 4 print(next(myiter)) # Output: 7 print(next(myiter)) # next(obj) is same as obj._next() # Output: 0 print(my_iter.__next()) # Output: 3 print(my_iter.__next()) # This will raise error, no items left next(my_iter)
输出
4 7 0 3 回溯(最近一次调用最后一次): 文件“”,第 24 行,在 中 下一个(my_iter) 停止迭代

一种更优雅的自动迭代方式是使用for 循环。使用它,我们可以迭代任何可以返回迭代器的对象,例如列表、字符串、文件等。
>>> for element in my_list: … print(element) … 4 7 0 3


迭代器 for 循环的工作

正如我们在上面的例子中看到的,for循环能够自动遍历列表。
事实上,for循环可以迭代任何可迭代对象。让我们仔细看看for循环是如何在 Python 中实际实现的。
for element in iterable: # do something with element
实际上是实现为。
# create an iterator object from that iterable iter_obj = iter(iterable) # infinite loop while True: try: # get the next item element = next(iter_obj) # do something with element except StopIteration: # if StopIteration is raised, break from loop break
所以在内部,for循环iter_obj通过调用iter()可迭代对象来创建一个迭代器对象。
具有讽刺意味的是,这个for循环实际上是一个无限的while 循环
在循环内部,它调用next()获取下一个元素并for使用此值执行循环体。在所有物品用完后,StopIteration升起并在内部捕获并结束循环。请注意,任何其他类型的异常都会通过。


构建自定义迭代器

在 Python 中从头开始构建迭代器很容易。我们只需要实现iter()和next()方法。
iter()方法返回迭代器对象本身。如果需要,可以执行一些初始化。
next()方法必须返回序列中的下一项。在到达结束时以及在随后的调用中,它必须提高StopIteration。
在这里,我们展示了一个示例,它将在每次迭代中为我们提供下一个 2 的幂。幂指数从零开始到用户设置的数字。
如果您对面向对象编程一无所知,请访问 Python Object-Oriented Programming

class PowTwo: “””Class to implement an iterator of powers of two””” def init(self, max=0): self.max = max def iter(self): self.n = 0 return self def next(self): if self.n <= self.max: result = 2 self.n self.n += 1 return result else: raise StopIteration # create an object numbers = PowTwo(3) # create an iterable from the object i = iter(numbers) # Using next to get to the next iterator element print(next(i)) print(next(i)) print(next(i)) print(next(i)) print(next(i))
输出**
1 2 4 8 回溯(最近一次调用最后一次): 中的文件“/home/bsoyuj/Desktop/Untitled-1.py”,第 32 行 打印(下一个(i)) 文件“”,第 18 行,在 next 中 引发停止迭代 停止迭代
我们还可以使用for循环来迭代我们的迭代器类。
>>> for i in PowTwo(5): … print(i) … 1 2 4 8 16 32


Python 无限迭代器

迭代器对象中的项目没有必要被耗尽。可以有无限的迭代器(永远不会结束)。我们在处理这样的迭代器时必须小心。
这是一个演示无限迭代器的简单示例。
内置函数 iter()可以用两个参数称为其中第一个参数必须是一个可调用对象(功能)和第二个是定点。迭代器调用这个函数直到返回值等于哨兵。
>>> int() 0 >>> inf = iter(int,1) >>> next(inf) 0 >>> next(inf) 0
我们可以看到int()函数总是返回 0。所以传递它 asiter(int,1)将返回一个迭代器,该迭代器调用int()直到返回值等于 1。这永远不会发生,我们得到了一个无限迭代器。
我们也可以构建我们自己的无限迭代器。理论上,以下迭代器将返回所有奇数。

class InfIter: “””Infinite iterator to return all odd numbers””” def iter(self): self.num = 1 return self def next(self): num = self.num self.num += 2 return num
示例运行如下。
>>> a = iter(InfIter()) >>> next(a) 1 >>> next(a) 3 >>> next(a) 5 >>> next(a) 7
等等…
在迭代这些类型的无限迭代器时,请注意包含终止条件。
使用迭代器的好处是可以节省资源。如上所示,我们可以在不将整个数字系统存储在内存中的情况下获取所有奇数。我们可以在有限内存中拥有无限项(理论上)。
在 Python 中有一种更简单的方法来创建迭代器。要了解更多信息,请访问:使用 yield 的 Python 生成器