迭代是Python访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象,而生成器则是实现迭代器协议的生成数据的简单函数。迭代器只能往前不会后退,而生成器可以。迭代器和生成器都是Python中强大的数据类型,具有惰性计算的特点,即不会立即产生所有结果,而是逐步产生。
迭代器是一个对象,可以用来遍历可迭代对象(如列表、元组、字典等)中的元素。迭代器是一个具有__next__
方法的对象,每次调用__next__
方法时,迭代器会返回它的下一个值。如果迭代器没有更多的值可以返回,调用__next__
方法会引发一个StopIteration
异常。迭代器只能往前不会后退,这意味着无法重新访问已经遍历过的元素。迭代器可以用于遍历大型数据集,因为它们在内存中只存储一个元素,而不是一次性加载整个数据集。
__iter__
方法返回迭代器本身,通常是self。
__next__
方法返回可迭代对象的下一个元素,如果没有元素可迭代,会引发StopIteration
异常。
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 # 抛出异常
value = self.data[self.index]
self.index += 1
return value
my_iter = MyIterator([1, 2, 3, 4, 5])
for item in my_iter:
print(item)
# 定义二叉树节点类
class BinaryTree(object):
def __init__(self, value, left=None, right=None):
self.value = value # 节点值
self.left = left # 左子树
self.right = right # 右子树
def __iter__(self):
return InorderIterator(self)
# 定义中序遍历的迭代器类
class InorderIterator(object):
def __init__(self, node):
self.node = node # 当前节点
self.stack = [] # 用于辅助中序遍历的栈
def __next__(self):
# 如果栈非空或者当前节点非空
if len(self.stack) > 0 or self.node is not None:
while self.node is not None:
self.stack.append(self.node) # 将当前节点入栈
self.node = self.node.left # 移动到左子树
node = self.stack.pop() # 弹出栈顶节点
self.node = node.right # 移动到右子树
return node.value # 返回节点的值
else:
raise StopIteration() # 遍历完成时抛出异常
# 创建一个二叉树
tree = BinaryTree(
left=BinaryTree(
left=BinaryTree(1),
value=2,
right=BinaryTree(
left=BinaryTree(3),
value=4,
right=BinaryTree(5)
),
),
value=6,
right=BinaryTree(
value=7,
right=BinaryTree(8)
)
)
for value in tree:
print(value)
上述代码定义了一个二叉树和中序遍历的迭代器,然后使用迭代器来遍历树的节点并打印节点的值。
生成器是一种特殊的迭代器,可以通过函数来创建。生成器函数使用yield
关键字来产生值,而不是使用return。实际上,生成器是实现迭代器协议的生成数据的简单函数,本质上属于迭代器。生成器用于“凭空”生成元素,每次调用生成器的函数时,它都会计算一个新的值,并将其添加到结果集中。生成器函数在每次调用时不会重新启动,而是从上一次yield语句的位置继续执行。生成器在迭代时会自动管理状态,不需要手动实现 __iter__
和__next__
方法。
def my_generator(data):
for item in data:
yield item
gen = my_generator([1, 2, 3, 4, 5])
for item in gen:
print(item)
# 定义二叉树节点类
class BinaryTree(object):
def __init__(self, value, left=None, right=None):
self.value = value # 节点的值
self.left = left # 左子树
self.right = right # 右子树
# 使用生成器实现中序遍历的函数
def traversal(node):
if node is not None:
yield from traversal(node.left) # 递归左子树
yield node.value # 生成当前节点的值
yield from traversal(node.right) # 递归右子树
# 创建一个二叉树
tree = BinaryTree(
left=BinaryTree(
left=BinaryTree(1),
value=2,
right=BinaryTree(
left=BinaryTree(3),
value=4,
right=BinaryTree(5)
),
),
value=6,
right=BinaryTree(
value=7,
right=BinaryTree(8)
)
)
# 使用生成器进行中序遍历并打印节点值
for value in traversal(tree):
print(value)
总而言之,Python的迭代器是一种可以遍历集合中元素的对象,必须实现__iter__
和__next__
方法。__iter__
返回迭代器自身,__next__
用于获取下一个元素,当没有元素可迭代时,会引发StopIteration
异常。
生成器则是一种特殊的迭代器,使用函数中的yield
关键字来生成值,但不会中断函数的执行。生成器提供了一种更简洁的方式来创建可迭代对象,它按需生成元素,因此可以节省内存。生成器函数在每次调用yield
时会保存当前状态,以便下次从相同位置继续执行,使得迭代更加灵活和高效,在处理大规模数据集时非常有用。