1. 什么是迭代器?

迭代器(Iterator)是 Python 中一种实现了迭代协议的对象,它允许我们逐个访问集合中的元素,而不需要知道集合的内部结构。迭代器必须实现两个方法:

  • __iter__():返回迭代器对象本身
  • __next__():返回下一个元素,如果没有更多元素则抛出 StopIteration 异常

1.1 迭代器的基本使用

1
2
3
4
5
6
7
8
9
10
11
12
# 创建一个迭代器
numbers = [1, 2, 3, 4, 5]
iterator = iter(numbers)

# 使用 next() 函数获取下一个元素
print(next(iterator)) # 输出: 1
print(next(iterator)) # 输出: 2
print(next(iterator)) # 输出: 3

# 使用 for 循环遍历(自动处理 StopIteration 异常)
for num in iterator:
print(num) # 输出: 4, 5

1.2 自定义迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Countdown:
def __init__(self, start):
self.start = start

def __iter__(self):
return self

def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1

# 使用自定义迭代器
countdown = Countdown(5)
for num in countdown:
print(num) # 输出: 5, 4, 3, 2, 1

2. 什么是可迭代对象?

可迭代对象(Iterable)是指实现了 __iter__() 方法的对象,它可以生成一个迭代器。常见的可迭代对象包括:

  • 序列类型:列表、元组、字符串
  • 集合类型:集合、字典
  • 文件对象
  • 生成器

2.1 检查可迭代对象

1
2
3
4
5
6
from collections.abc import Iterable

print(isinstance([], Iterable)) # 输出: True
print(isinstance({}, Iterable)) # 输出: True
print(isinstance("hello", Iterable)) # 输出: True
print(isinstance(123, Iterable)) # 输出: False

2.2 可迭代对象与迭代器的区别

  • 可迭代对象:实现了 __iter__() 方法,返回一个迭代器
  • 迭代器:实现了 __iter__()__next__() 方法,用于逐个访问元素

3. 什么是生成器?

生成器(Generator)是一种特殊的迭代器,它使用 yield 语句来产生值,而不是一次性计算所有值。生成器具有惰性计算的特性,只在需要时才生成值,从而节省内存。

3.1 生成器表达式

1
2
3
4
5
6
7
# 生成器表达式(使用圆括号)
squares = (x ** 2 for x in range(10))
print(type(squares)) # 输出: <class 'generator'>

# 遍历生成器
for square in squares:
print(square) # 输出: 0, 1, 4, 9, 16, 25, 36, 49, 64, 81

3.2 生成器函数

1
2
3
4
5
6
7
8
def countdown(n):
while n > 0:
yield n
n -= 1

# 使用生成器函数
for num in countdown(5):
print(num) # 输出: 5, 4, 3, 2, 1

4. 生成器的工作原理

生成器函数在执行时,会在遇到 yield 语句时暂停执行,保存当前的状态(包括局部变量和执行位置),并返回 yield 后面的值。当再次调用 next() 函数时,生成器会从暂停的位置继续执行,直到遇到下一个 yield 语句或函数结束。

4.1 生成器的状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def simple_generator():
print("开始执行")
yield 1
print("继续执行")
yield 2
print("执行结束")

# 创建生成器对象
gen = simple_generator()

# 第一次调用 next()
print(next(gen)) # 输出: 开始执行
# 输出: 1

# 第二次调用 next()
print(next(gen)) # 输出: 继续执行
# 输出: 2

# 第三次调用 next()
print(next(gen)) # 输出: 执行结束
# 抛出 StopIteration 异常

5. 生成器的高级特性

5.1 生成器的 send() 方法

生成器的 send() 方法可以向生成器发送值,并恢复执行。

1
2
3
4
5
6
7
8
9
10
11
def echo_generator():
response = yield "请输入一个值:"
while response != "exit":
response = yield f"你输入的是:{response}"

# 使用 send() 方法
gen = echo_generator()
print(next(gen)) # 启动生成器,输出: 请输入一个值:
print(gen.send("Hello")) # 发送值并获取结果,输出: 你输入的是:Hello
print(gen.send("World")) # 发送值并获取结果,输出: 你输入的是:World
print(gen.send("exit")) # 发送 exit,生成器结束,抛出 StopIteration 异常

5.2 生成器的 throw() 方法

生成器的 throw() 方法可以向生成器抛出异常。

1
2
3
4
5
6
7
8
9
10
11
12
def error_generator():
try:
yield 1
yield 2
yield 3
except ValueError as e:
yield f"捕获到异常:{e}"

# 使用 throw() 方法
gen = error_generator()
print(next(gen)) # 输出: 1
print(gen.throw(ValueError, "自定义错误")) # 输出: 捕获到异常:自定义错误

5.3 生成器的 close() 方法

生成器的 close() 方法可以关闭生成器,释放资源。

1
2
3
4
5
6
7
8
9
10
11
12
def infinite_generator():
i = 0
while True:
yield i
i += 1

# 使用 close() 方法
gen = infinite_generator()
print(next(gen)) # 输出: 0
print(next(gen)) # 输出: 1
gen.close() # 关闭生成器
print(next(gen)) # 抛出 StopIteration 异常

6. 迭代器和生成器的应用场景

6.1 处理大型数据集

1
2
3
4
5
6
7
8
9
# 处理大型文件
def read_large_file(filename):
with open(filename, 'r') as f:
for line in f:
yield line.strip()

# 惰性读取文件内容
for line in read_large_file('large_file.txt'):
process_line(line)

6.2 实现无限序列

1
2
3
4
5
6
7
8
9
10
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b

# 获取斐波那契数列的前 10 项
fib = fibonacci()
for _ in range(10):
print(next(fib)) # 输出: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34

6.3 管道处理数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def filter_even(numbers):
for num in numbers:
if num % 2 == 0:
yield num

def square(numbers):
for num in numbers:
yield num ** 2

def sum_numbers(numbers):
total = 0
for num in numbers:
total += num
return total

# 数据处理管道
numbers = range(10)
even_numbers = filter_even(numbers)
squared_numbers = square(even_numbers)
total = sum_numbers(squared_numbers)
print(total) # 输出: 0 + 4 + 16 + 36 + 64 = 120

7. 迭代工具

Python 提供了一些内置的迭代工具,用于处理可迭代对象:

7.1 itertools 模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import itertools

# 无限迭代器
counter = itertools.count(1) # 从 1 开始计数
print(next(counter)) # 输出: 1
print(next(counter)) # 输出: 2

# 循环迭代器
cycler = itertools.cycle(['A', 'B', 'C'])
print(next(cycler)) # 输出: A
print(next(cycler)) # 输出: B
print(next(cycler)) # 输出: C
print(next(cycler)) # 输出: A

# 重复迭代器
repeater = itertools.repeat('Hello', 3) # 重复 3 次
for item in repeater:
print(item) # 输出: Hello, Hello, Hello

7.2 内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# map() 函数
numbers = [1, 2, 3, 4, 5]
squared = map(lambda x: x ** 2, numbers)
print(list(squared)) # 输出: [1, 4, 9, 16, 25]

# filter() 函数
evens = filter(lambda x: x % 2 == 0, numbers)
print(list(evens)) # 输出: [2, 4]

# zip() 函数
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
for name, age in zip(names, ages):
print(f"{name}: {age}") # 输出: Alice: 25, Bob: 30, Charlie: 35

8. 生成器表达式与列表推导式的对比

8.1 内存使用

1
2
3
4
5
6
7
8
9
import sys

# 列表推导式(一次性生成所有值)
list_comp = [x ** 2 for x in range(1000000)]
print(f"列表推导式内存使用: {sys.getsizeof(list_comp)} 字节")

# 生成器表达式(惰性计算)
gen_expr = (x ** 2 for x in range(1000000))
print(f"生成器表达式内存使用: {sys.getsizeof(gen_expr)} 字节")

8.2 执行速度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import time

# 列表推导式
tart = time.time()
list_comp = [x ** 2 for x in range(1000000)]
sum(list_comp)
end = time.time()
print(f"列表推导式耗时: {end - start:.6f} 秒")

# 生成器表达式
start = time.time()
gen_expr = (x ** 2 for x in range(1000000))
sum(gen_expr)
end = time.time()
print(f"生成器表达式耗时: {end - start:.6f} 秒")

9. 自定义可迭代对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class MyRange:
def __init__(self, start, end, step=1):
self.start = start
self.end = end
self.step = step

def __iter__(self):
return self.MyRangeIterator(self)

class MyRangeIterator:
def __init__(self, my_range):
self.my_range = my_range
self.current = my_range.start

def __iter__(self):
return self

def __next__(self):
if self.current >= self.my_range.end:
raise StopIteration
value = self.current
self.current += self.my_range.step
return value

# 使用自定义可迭代对象
for i in MyRange(0, 10, 2):
print(i) # 输出: 0, 2, 4, 6, 8