# 生成器与迭代器

URL: https://caijiao.org/python/ch10/generators
Source: docs/python/ch10/generators.md
Description: 本章介绍 Python 中的生成器与迭代器，讲解它们的定义、创建方式以及在实际编程中的应用。

在 [Python](/python/) 中，生成器和迭代器是用于处理数据流的一种重要工具。它们帮助我们高效地处理大数据集，减少内存的消耗，尤其适用于需要逐个处理元素的场景，如读取大文件或处理大规模数据。

## 迭代器

迭代器是一种对象，它实现了迭代协议，可以逐个返回集合中的元素。迭代器有两个核心方法：

- `__iter__()`：返回迭代器对象本身。
- `__next__()`：返回集合的下一个元素。如果没有元素可返回，抛出 `StopIteration` 异常。

### 迭代器示例

```python
class MyIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        self.current += 1
        return self.current - 1

# 创建迭代器
iterator = MyIterator(0, 3)

# 使用迭代器
for number in iterator:
    print(number)
```

输出：

```
0
1
2
```

## 生成器

生成器是一种特殊类型的迭代器，它允许我们通过 `yield` 关键字逐步返回数据。与常规的迭代器不同，生成器函数在每次调用 `yield` 时暂停，保留当前的执行状态，直到下次 `next()` 被调用时恢复。

生成器具有惰性求值的特点，即只有在需要时才会生成数据，这使得它在处理大量数据时非常高效。

### 生成器函数示例

```python
def count_up_to(max):
    count = 1
    while count <= max:
        yield count
        count += 1

# 创建生成器
counter = count_up_to(3)

# 使用生成器
for number in counter:
    print(number)
```

输出：

```
1
2
3
```

### 生成器表达式

除了使用 `yield` 创建生成器外，我们还可以使用生成器表达式来创建生成器，语法与列表推导式类似，但使用圆括号 `()`。

```python
gen = (x * x for x in range(5))
for i in gen:
    print(i)
```

输出：

```
0
1
4
9
16
```

## 迭代器与生成器的对比

- **内存占用**：迭代器和生成器都使用惰性求值，但生成器通常具有更小的内存占用，因为它是逐步生成数据的。
- **创建方式**：迭代器需要自己实现类并定义 `__iter__()` 和 `__next__()` 方法；而生成器则通过函数与 `yield` 关键字实现，简洁易用。
- **性能**：生成器通过 `yield` 生成数据，适用于大数据量的场景，避免一次性加载大量数据。

## 迭代器与生成器的应用场景

- **迭代器**：适用于需要自定义迭代逻辑的场景。
- **生成器**：适用于需要处理大数据、流式数据处理，且希望延迟生成结果的场景。

## 总结

- 迭代器是实现了迭代协议的对象，可以逐个返回元素。
- 生成器是一个特殊类型的迭代器，通过 `yield` 逐步生成数据。
- 生成器和迭代器可以有效减少内存占用，适用于处理大量数据的场景。
- 生成器提供了简洁的语法和高效的性能，尤其适用于流式数据处理。

使用生成器和迭代器能够显著提高程序的性能，尤其在处理大数据集或流式数据时具有独特优势。
