5.1 Iterable
和 Iterator
如你所知,迭代器是实现了迭代器协议的对象,它允许 逐个获取集合中的元素。 迭代器在 Python 中被广泛使用,用于遍历列表、元组和字符串等序列的元素。
让我们来看看迭代器是如何构成的以及如何使用它们。
可迭代对象 (Iterable)
要让一个对象可以用 for
循环遍历,它必须是可迭代的 – Iterable
。这意味着我们的对象必须
实现 方法 __iter__()
,
它返回一个迭代器对象。
迭代器对象 (Iterator)
这是一个特殊的对象,具有
函数 __next__()
用于返回
序列的下一个元素。当元素
结束时,方法 __next__()
会引发
StopIteration
异常
作为结束迭代的标志。
迭代器还必须实现方法 __iter__()
,
它返回迭代器自身。
使用 Python 内置函数的示例
在这个例子中,列表
numbers 是一个可迭代对象。
我们通过 iter()
函数获取迭代器,然后使用
next()
函数遍历元素,直到引发
StopIteration
异常。
# 可迭代对象
numbers = [1, 2, 3, 4, 5]
# 从可迭代对象中获取迭代器
iterator = iter(numbers)
# 使用迭代器遍历元素
try:
while True:
number = next(iterator)
print(number)
except StopIteration:
pass
这正是当你写类似代码时发生的事情:
# 可迭代对象
numbers = [1, 2, 3, 4, 5]
for number in numbers:
print(number)
5.2 迭代器的本质
迭代器是帮助我们逐个遍历元素组的某个对象。它的实现可以有所不同。让我们 编写自己的类,来实现迭代器的所有要求。
步骤 1. 首先创建一个类
让它依次返回从 start
到
end
的数字
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
步骤 2. 支持 __iter__
函数
现在我们需要为它添加一个 __iter__
函数,
它会返回一个调用 __next()__
函数的迭代器对象。我们会返回
我们自己的对象的引用——这是被允许的。
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
步骤 3. 支持 __next__
函数
现在我们需要为我们的迭代器对象添加一个 __next__
函数,它会返回
列表中的下一个元素。我们会简单地使用变量 current
:
def __next__(self):
current = self.current
self.current += 1
return current
步骤 4. 停止迭代器
如果迭代器已经返回了所有计划的值,它应该抛出 StopIteration
异常。让我们
稍微修改一下我们的最后一个函数:
def __next__(self):
if self.current >= self.end:
raise StopIteration
current = self.current
self.current += 1
return current
很好。现在我们可以使用我们的迭代器了。以下是我们全部代码的示例:
class MyIterator:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.current >= self.end:
raise StopIteration
current = self.current
self.current += 1
return current
# 创建自定义迭代器的实例
my_iter = MyIterator(1, 5)
# 使用迭代器遍历元素
for num in my_iter:
print(num)
5.3 正确的迭代器
前一个例子中的迭代器有什么问题?是的,这是一个迭代器,它是可用的,但它太简单了。用它 不能同时用不同的迭代器遍历同一个元素集合。
更为正确的做法是在 __iter__
方法中返回的不是自己的引用,而是
一个独立的对象,
它可以正确地返回所有元素。
示例:
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
return MyIterator(self.data)
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
item = self.data[self.index]
self.index += 1
return item
# 使用
my_iterable = MyIterable([1, 2, 3, 4])
for item in my_iterable:
print(item)
在这个例子中,我们有两个类——第一个传入一个集合,我们会用迭代器遍历它。
第二个是迭代器,它在 next()
方法中返回集合的元素。它也相当简单,
但这正是你应该在你的类中添加迭代器的方式。
GO TO FULL VERSION