迭代器模式
迭代器模式(Iterator Pattern)提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
问题定义
场景1:遍历不同集合
# ❌ 问题:暴露内部结构
class ArrayCollection:
"""数组集合"""
def __init__(self):
self.items = []
def add(self, item):
self.items.append(item)
# 问题:直接暴露内部列表
def get_items(self):
return self.items
class LinkedList:
"""链表"""
def __init__(self):
self.head = None
def add(self, item):
# 链表添加逻辑...
pass
# 问题:遍历方式完全不同
def get_items(self):
current = self.head
items = []
while current:
items.append(current.data)
current = current.next
return items
# 问题:客户端需要知道不同的遍历方式
array = ArrayCollection()
array.add(1)
array.add(2)
array.add(3)
for item in array.get_items(): # 使用列表遍历
print(item)
场景2:多种遍历方式
# ❌ 问题:无法支持多种遍历方式
class BinaryTree:
"""二叉树"""
def __init__(self, value):
self.value = value
self.left = None
self.right = None
# 问题:只能提供一种遍历方式
def traverse(self):
# 只能前序遍历
print(self.value)
if self.left:
self.left.traverse()
if self.right:
self.right.traverse()
# 想要中序、后序遍历需要添加新方法
解决方案
迭代器模式提供统一的遍历接口,隐藏集合的内部结构。
classDiagram
class Iterator {
<>
+hasNext()
+next()
}
class Aggregate {
<>
+createIterator()
}
class ConcreteIterator {
-aggregate: Aggregate
-current: int
+hasNext()
+next()
}
class ConcreteAggregate {
-items: Object[]
+createIterator()
}
Iterator <|-- ConcreteIterator
Aggregate <|-- ConcreteAggregate
ConcreteIterator o-- ConcreteAggregate : traverses
标准实现
迭代器接口
from abc import ABC, abstractmethod
class Iterator(ABC):
"""迭代器接口"""
@abstractmethod
def has_next(self):
"""是否有下一个元素"""
pass
@abstractmethod
def next(self):
"""获取下一个元素"""
pass
class Aggregate(ABC):
"""聚合接口"""
@abstractmethod
def create_iterator(self):
"""创建迭代器"""
pass
具体聚合和迭代器
class ArrayCollection(Aggregate):
"""数组集合"""
def __init__(self):
self._items = []
def add(self, item):
self._items.append(item)
def create_iterator(self):
return ArrayIterator(self)
class ArrayIterator(Iterator):
"""数组迭代器"""
def __init__(self, collection):
self._collection = collection
self._current = 0
def has_next(self):
return self._current < len(self._collection._items)
def next(self):
if not self.has_next():
raise StopIteration("没有更多元素")
item = self._collection._items[self._current]
self._current += 1
return item
客户端使用
# 创建集合
collection = ArrayCollection()
collection.add("苹果")
collection.add("香蕉")
collection.add("橙子")
# 创建迭代器
iterator = collection.create_iterator()
# 遍历
print("遍历数组:")
while iterator.has_next():
item = iterator.next()
print(f" {item}")
Python内置迭代器
Python内置了迭代器协议,使用__iter__和__next__方法:
class MyCollection:
"""自定义集合 - Python迭代器"""
def __init__(self):
self._items = []
def add(self, item):
self._items.append(item)
def __iter__(self):
"""返回迭代器"""
return MyIterator(self)
def __len__(self):
return len(self._items)
class MyIterator:
"""自定义迭代器"""
def __init__(self, collection):
self._collection = collection
self._current = 0
def __iter__(self):
"""迭代器也是可迭代的"""
return self
def __next__(self):
"""获取下一个元素"""
if self._current >= len(self._collection._items):
raise StopIteration
item = self._collection._items[self._current]
self._current += 1
return item
# 使用
collection = MyCollection()
collection.add("A")
collection.add("B")
collection.add("C")
print("使用for循环遍历:")
for item in collection:
print(f" {item}")
print("\n使用迭代器:")
iterator = iter(collection)
print(f" {next(iterator)}")
print(f" {next(iterator)}")
print(f" {next(iterator)}")
实战应用
应用1:二叉树遍历
from abc import ABC, abstractmethod
class TreeNode:
"""二叉树节点"""
def __init__(self, value):
self.value = value
self.left = None
self.right = None
class TreeIterator(ABC):
"""树迭代器接口"""
@abstractmethod
def __iter__(self):
pass
class PreOrderIterator(TreeIterator):
"""前序遍历迭代器"""
def __init__(self, root):
self._root = root
self._stack = []
if root:
self._stack.append(root)
def __iter__(self):
return self
def __next__(self):
if not self._stack:
raise StopIteration
node = self._stack.pop()
# 右子树先入栈,后出栈
if node.right:
self._stack.append(node.right)
if node.left:
self._stack.append(node.left)
return node.value
class InOrderIterator(TreeIterator):
"""中序遍历迭代器"""
def __init__(self, root):
self._current = root
self._stack = []
self._push_left(self._current)
def _push_left(self, node):
"""将左子树全部压入栈"""
while node:
self._stack.append(node)
node = node.left
def __iter__(self):
return self
def __next__(self):
if not self._stack:
raise StopIteration
node = self._stack.pop()
self._push_left(node.right)
return node.value
class PostOrderIterator(TreeIterator):
"""后序遍历迭代器"""
def __init__(self, root):
self._root = root
self._stack = [(root, False)]
def __iter__(self):
return self
def __next__(self):
while self._stack:
node, visited = self._stack.pop()
if not node:
continue
if visited:
return node.value
else:
# 后序遍历:右、左、根
self._stack.append((node, True))
self._stack.append((node.right, False))
self._stack.append((node.left, False))
raise StopIteration
# 使用
# 构建二叉树
# 1
# / \
# 2 3
# / \
# 4 5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print("前序遍历:")
for value in PreOrderIterator(root):
print(f" {value}", end=" ")
print("\n")
print("中序遍历:")
for value in InOrderIterator(root):
print(f" {value}", end=" ")
print("\n")
print("后序遍历:")
for value in PostOrderIterator(root):
print(f" {value}", end=" ")
print()
应用2:员工组织架构遍历
from abc import ABC, abstractmethod
class Employee:
"""员工"""
def __init__(self, name, position, salary):
self.name = name
self.position = position
self.salary = salary
self.subordinates = []
def add_subordinate(self, employee):
self.subordinates.append(employee)
def __str__(self):
return f"{self.name} ({self.position}) - ${self.salary}"
class EmployeeIterator(ABC):
"""员工迭代器接口"""
@abstractmethod
def __iter__(self):
pass
class DFSIterator(EmployeeIterator):
"""深度优先遍历迭代器"""
def __init__(self, root):
self._stack = [root]
def __iter__(self):
return self
def __next__(self):
if not self._stack:
raise StopIteration
employee = self._stack.pop()
# 子员工入栈(反向,保证顺序)
for subordinate in reversed(employee.subordinates):
self._stack.append(subordinate)
return employee
class BFSIterator(EmployeeIterator):
"""广度优先遍历迭代器"""
def __init__(self, root):
from collections import deque
self._queue = deque([root])
def __iter__(self):
return self
def __next__(self):
if not self._queue:
raise StopIteration
employee = self._queue.popleft()
# 子员工入队
for subordinate in employee.subordinates:
self._queue.append(subordinate)
return employee
# 构建组织架构
ceo = Employee("Alice", "CEO", 150000)
vp_engineering = Employee("Bob", "VP Engineering", 120000)
vp_sales = Employee("Charlie", "VP Sales", 120000)
manager1 = Employee("David", "Engineering Manager", 90000)
manager2 = Employee("Eve", "Engineering Manager", 90000)
dev1 = Employee("Frank", "Software Engineer", 80000)
dev2 = Employee("Grace", "Software Engineer", 80000)
dev3 = Employee("Henry", "Software Engineer", 80000)
# 构建层级
ceo.add_subordinate(vp_engineering)
ceo.add_subordinate(vp_sales)
vp_engineering.add_subordinate(manager1)
vp_engineering.add_subordinate(manager2)
manager1.add_subordinate(dev1)
manager1.add_subordinate(dev2)
manager2.add_subordinate(dev3)
# 遍历
print("深度优先遍历:")
for employee in DFSIterator(ceo):
print(f" {employee}")
print("\n广度优先遍历:")
for employee in BFSIterator(ceo):
print(f" {employee}")
应用3:菜单系统
from abc import ABC, abstractmethod
class MenuItem:
"""菜单项"""
def __init__(self, name, description, price, vegetarian=False):
self.name = name
self.description = description
self.price = price
self.vegetarian = vegetarian
def __str__(self):
v = "(V)" if self.vegetarian else ""
return f"{self.name} {v} - ${self.price:.2f}\n {self.description}"
class Menu(ABC):
"""菜单接口"""
@abstractmethod
def create_iterator(self):
pass
class BreakfastMenu(Menu):
"""早餐菜单"""
def __init__(self):
self._items = []
def add_item(self, name, description, price, vegetarian=False):
item = MenuItem(name, description, price, vegetarian)
self._items.append(item)
def create_iterator(self):
return BreakfastIterator(self._items)
class LunchMenu(Menu):
"""午餐菜单"""
def __init__(self):
self._items = []
def add_item(self, name, description, price, vegetarian=False):
item = MenuItem(name, description, price, vegetarian)
self._items.append(item)
def create_iterator(self):
return LunchIterator(self._items)
class BreakfastIterator:
"""早餐菜单迭代器"""
def __init__(self, items):
self._items = items
self._position = 0
def __iter__(self):
return self
def __next__(self):
if self._position >= len(self._items):
raise StopIteration
item = self._items[self._position]
self._position += 1
return item
class LunchIterator:
"""午餐菜单迭代器"""
def __init__(self, items):
self._items = list(items.items())
self._position = 0
def __iter__(self):
return self
def __next__(self):
if self._position >= len(self._items):
raise StopIteration
key, item = self._items[self._position]
self._position += 1
return item
# 使用
breakfast = BreakfastMenu()
breakfast.add_item("煎蛋", "两个煎蛋", 2.99, True)
breakfast.add_item("培根", " crispy bacon", 3.99)
breakfast.add_item("吐司", "烤吐司", 1.99, True)
lunch = LunchMenu()
lunch.add_item("汉堡", "牛肉汉堡", 5.99)
lunch.add_item("沙拉", "凯撒沙拉", 4.99, True)
lunch.add_item("汤", "蘑菇汤", 2.99, True)
# 创建菜单列表
menus = [breakfast, lunch]
print("=== 早餐 ===")
for item in breakfast.create_iterator():
print(f" {item}")
print("\n=== 午餐 ===")
for item in lunch.create_iterator():
print(f" {item}")
print("\n=== 所有菜单 ===")
for menu in menus:
for item in menu.create_iterator():
print(f" {item}")
生成器作为迭代器
Python的生成器是创建迭代器的简洁方式:
def fibonacci_generator(n):
"""斐波那契数列生成器"""
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
# 使用生成器
print("斐波那契数列:")
for num in fibonacci_generator(10):
print(f" {num}", end=" ")
print()
# 等价的迭代器实现
class FibonacciIterator:
"""斐波那契数列迭代器"""
def __init__(self, n):
self.n = n
self.current = 0
self.a, self.b = 0, 1
def __iter__(self):
return self
def __next__(self):
if self.current >= self.n:
raise StopIteration
result = self.a
self.a, self.b = self.b, self.a + self.b
self.current += 1
return result
# 使用迭代器
print("\n使用迭代器:")
for num in FibonacciIterator(10):
print(f" {num}", end=" ")
print()
优缺点
✅ 优点
| 优点 | 说明 |
|---|---|
| 统一接口 | 不同的集合有相同的遍历方式 |
| 隐藏内部 | 不暴露集合的内部结构 |
| 多种遍历 | 可以实现不同的遍历策略 |
| 解耦 | 集合和遍历分离 |
❌ 缺点
| 缺点 | 说明 |
|---|---|
| 复杂度 | 简单遍历可能过度设计 |
| 性能 | 迭代器有额外开销 |
Python迭代器协议
Python的迭代器协议:
- __iter__() 返回迭代器对象
- __next__() 返回下一个元素
# 可迭代对象 vs 迭代器
iterable = [1, 2, 3] # 可迭代对象
iterator = iter(iterable) # 迭代器
# 可迭代对象有__iter__
print(hasattr(iterable, '__iter__')) # True
# 迭代器有__iter__和__next__
print(hasattr(iterator, '__iter__')) # True
print(hasattr(iterator, '__next__')) # True
本章要点
- ✅ 迭代器模式提供统一的遍历接口
- ✅ 隐藏集合的内部结构
- ✅ 支持多种遍历策略(前序、中序、后序等)
- ✅ Python内置迭代器协议
- ✅ 生成器是创建迭代器的简洁方式
- ✅ 集合和遍历逻辑解耦
下一步:状态模式 🚀