什么是 Iterator(迭代器)?
核心思想: 迭代器是一种设计模式,它提供了一种方法,能够顺序访问一个聚合对象(如列表、容器)中的各个元素,而又不需要暴露该对象的内部表示。
你可以把迭代器想象成一个智能指针,它知道如何在容器中“遍历”或“移动”,并访问每个元素。
关键点:
- 抽象了遍历过程:无论底层数据结构是数组、链表、树还是哈希表,使用迭代器的代码看起来都差不多。
- 统一了访问接口:为不同的容器提供了一个统一的遍历访问接口。
- 保护了数据:用户通过迭代器访问元素,而不需要知道容器是如何存储这些元素的。
C++ 中的迭代器
在 C++ 中,迭代器是 STL(标准模板库)的核心组成部分之一。它被设计得像指针一样,支持 *(解引用)、++(自增)等操作。
C++ 迭代器的类别:
- 输入迭代器:只读,且只能向前移动。
- 输出迭代器:只写,且只能向前移动。
- 前向迭代器:可读写,只能向前移动。
- 双向迭代器:可读写,能向前和向后移动(如
list,map,set的迭代器)。 - 随机访问迭代器:功能最强,可读写,能跳跃式移动(如
vector,deque的迭代器),支持+,-,[]等操作。
C++ 示例:
cpp
#include <iostream>
#include <vector>
#include <list>
int main() {
// 1. 使用 vector (随机访问迭代器)
std::vector<int> vec = {1, 2, 3, 4, 5};
std::cout << "Vector iteration: ";
// 使用 begin() 和 end() 获取迭代器
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " "; // 通过 * 解引用访问元素
}
std::cout << std::endl;
// 2. 使用 list (双向迭代器)
std::list<std::string> lst = {"Hello", "World", "C++"};
std::cout << "List iteration: ";
// 使用 auto 简化迭代器类型声明
for (auto it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 3. 反向迭代
std::cout << "Reverse iteration: ";
for (auto it = vec.rbegin(); it != vec.rend(); ++it) { // rbegin(), rend() 返回反向迭代器
std::cout << *it << " ";
}
std::cout << std::endl;
// 4. 基于范围的 for 循环 (底层也是使用迭代器)
std::cout << "Range-based for loop: ";
for (const auto& value : vec) {
std::cout << value << " ";
}
std::cout << std::endl;
return 0;
}输出:
Vector iteration: 1 2 3 4 5
List iteration: Hello World C++
Reverse iteration: 5 4 3 2 1
Range-based for loop: 1 2 3 4 5Python 中的迭代器
Python 的迭代器协议更加简洁和统一,是 Python for 循环的基础。
Python 迭代器协议: 一个对象是迭代器,当且仅当它实现了以下两个方法:
__iter__(): 返回迭代器对象本身(self)。__next__(): 返回容器的下一个元素。如果没有更多元素,则抛出StopIteration异常。
任何实现了 __iter__() 方法的对象都是 可迭代对象(Iterable)。当调用 iter() 函数时,它会调用对象的 __iter__() 方法来获取一个迭代器。
Python 示例:
python
# 1. 使用内置可迭代对象 (list, tuple, string, dict)
my_list = [1, 2, 3, 4, 5]
print("List iteration: ", end="")
# for 循环的底层机制:
# 1. 调用 iter(my_list) 获取一个迭代器
# 2. 重复调用 next(iterator) 获取值
# 3. 捕获 StopIteration 异常,结束循环
for item in my_list:
print(item, end=" ")
print()
# 2. 手动模拟 for 循环的过程
print("Manual iteration: ", end="")
iterator_obj = iter(my_list) # 获取迭代器,相当于 my_list.__iter__()
while True:
try:
item = next(iterator_obj) # 获取下一个元素,相当于 iterator_obj.__next__()
print(item, end=" ")
except StopIteration:
break
print()
# 3. 字典迭代
my_dict = {'a': 1, 'b': 2, 'c': 3}
print("Dict iteration (keys): ", end="")
for key in my_dict: # 默认迭代键
print(key, end=" ")
print()
print("Dict iteration (items): ", end="")
for key, value in my_dict.items():
print(f"{key}:{value}", end=" ")
print()
# 4. 创建一个自定义迭代器
class CountDown:
def __init__(self, start):
self.current = start
def __iter__(self):
# 返回迭代器对象本身,因为它自己就是迭代器
return self
def __next__(self):
if self.current <= 0:
raise StopIteration
else:
num = self.current
self.current -= 1
return num
print("Custom iterator: ", end="")
counter = CountDown(3)
for num in counter:
print(num, end=" ")
# 输出: 3 2 1输出:
List iteration: 1 2 3 4 5
Manual iteration: 1 2 3 4 5
Dict iteration (keys): a b c
Dict iteration (items): a:1 b:2 c:3
Custom iterator: 3 2 1C++ 与 Python 迭代器的对比总结
| 特性 | C++ | Python |
|---|---|---|
| 核心概念 | 类似智能指针,是 STL 算法的基石。 | 遵循迭代器协议(__iter__, __next__),是 for 循环的基础。 |
| 获取方式 | 通过容器的 begin(), end() 等方法。 | 通过内置函数 iter() 作用于可迭代对象。 |
| 遍历方式 | 使用 ++it 移动,*it 解引用。 | 使用 next() 函数或 __next__() 方法。 |
| 结束判断 | 将迭代器与 end() 返回的尾后迭代器比较。 | 捕获 StopIteration 异常。 |
| 类别 | 分为多种(输入、输出、前向、双向、随机访问),功能不同。 | 协议统一,但行为可能不同(如序列是顺序,字典是键的顺序)。 |
| 语法糖 | 基于范围的 for 循环 (for (auto x : container))。 | for 循环 (for x in iterable:)。 |
总结
- Iterator 是一个强大的抽象工具,它让你可以用相同或相似的代码来处理各种不同的数据结构。
- 在 C++ 中,迭代器是 STL 六大组件之一,与算法和容器紧密配合,是编写通用、高效 C++ 代码的关键。
- 在 Python 中,迭代器协议是语言的核心特性之一,它使得
for循环如此简洁和强大,并且可以轻松创建自定义的可迭代对象。
理解迭代器对于深入掌握这两种语言的编程范式至关重要。


