简介
迭代是Python访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象,而生成器则是实现迭代器协议的生成数据的简单函数。迭代器只能往前不会后退,而生成器可以。迭代器和生成器都是Python中强大的数据类型,具有惰性计算的特点,即不会立即产生所有结果,而是逐步产生。
迭代器(Iterator)
迭代器是一个对象,可以用来遍历可迭代对象(如列表、元组、字典等)中的元素。迭代器是一个具有__next__
方法的对象,每次调用__next__
方法时,迭代器会返回它的下一个值。如果迭代器没有更多的值可以返回,调用__next__
方法会引发一个StopIteration
异常。迭代器只能往前不会后退,这意味着无法重新访问已经遍历过的元素。迭代器可以用于遍历大型数据集,因为它们在内存中只存储一个元素,而不是一次性加载整个数据集。
__iter__
方法返回迭代器本身,通常是self。
__next__
方法返回可迭代对象的下一个元素,如果没有元素可迭代,会引发StopIteration
异常。
简单示例
class MyIterator:def __init__(self, data): # 初始化self.data = dataself.index = 0def __iter__(self):return selfdef __next__(self):if self.index >= len(self.data):raise StopIteration # 抛出异常value = self.data[self.index]self.index += 1return valuemy_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)
上述代码定义了一个二叉树和中序遍历的迭代器,然后使用迭代器来遍历树的节点并打印节点的值。
生成器(Generator)
生成器是一种特殊的迭代器,可以通过函数来创建。生成器函数使用yield
关键字来产生值,而不是使用return。实际上,生成器是实现迭代器协议的生成数据的简单函数,本质上属于迭代器。生成器用于“凭空”生成元素,每次调用生成器的函数时,它都会计算一个新的值,并将其添加到结果集中。生成器函数在每次调用时不会重新启动,而是从上一次yield语句的位置继续执行。生成器在迭代时会自动管理状态,不需要手动实现 __iter__
和__next__
方法。
简单示例
def my_generator(data):for item in data:yield itemgen = 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
时会保存当前状态,以便下次从相同位置继续执行,使得迭代更加灵活和高效,在处理大规模数据集时非常有用。