Logo
Published on

3.6.迭代协议

Authors
  • avatar
    Name
    xiaobai
    Twitter

1.概述

迭代协议是 Python 中用于支持迭代操作的核心机制,定义了对象如何被遍历的标准。理解迭代协议对于掌握 Python 的迭代机制至关重要。

2.核心概念关系图

img

3.核心概念

3.1.1. 可迭代对象 (Iterable)

  • 定义:实现了 __iter__() 方法的对象
  • 特点:可以被用于 for 循环,但不是迭代器
  • 常见类型list, tuple, str, dict, set
  • 核心方法__iter__() 返回一个迭代器

3.2.2. 迭代器 (Iterator)

  • 定义:实现了 __iter__()__next__() 方法的对象
  • 特点:本身也是可迭代对象,保持状态,一次性使用
  • 核心方法__next__() 返回下一个值,没有时抛出 StopIteration
  • 特性:惰性计算,一次只产生一个值

3.3.3. 生成器 (Generator)

  • 定义:特殊的迭代器,自动实现迭代协议
  • 创建方式
    • 生成器函数:使用 yield 关键字的函数
    • 生成器表达式:类似列表推导式,但使用圆括号
  • 特点:懒加载,按需生成值,节省内存

3.4.4. 生成器函数 (Generator Function)

  • 定义:包含 yield 关键字的函数
  • 特点:调用时不立即执行,返回生成器对象
  • 执行:每次调用 next() 时从上次 yield 位置继续

4.可迭代对象 (Iterable)

4.1.定义和特点

可迭代对象是实现了 __iter__() 方法的对象,可以被用于 for 循环等迭代操作。

核心特征

  • 实现了 __iter__() 方法
  • 可以被用于 for 循环
  • 不是迭代器,但可以生成迭代器
  • 每次迭代都会创建新的迭代器

4.2.常见可迭代对象

# 内置可迭代对象
string = "hello"          # 字符串
lst = [1, 2, 3]           # 列表
tup = (1, 2, 3)           # 元组
dct = {'a': 1, 'b': 2}    # 字典
st = {1, 2, 3}            # 集合

# 验证是否为可迭代对象
from collections.abc import Iterable
print(isinstance("hello", Iterable))  # True
print(isinstance(123, Iterable))      # False

4.3.可迭代对象的优势

  • 可重复遍历:每次调用 iter() 都返回新的迭代器
  • 内存效率:不需要预先存储所有数据
  • 灵活性:支持多种迭代方式
  • 兼容性:与 Python 内置函数无缝配合

4.4.自定义可迭代对象

自定义可迭代对象是指实现了 __iter__() 方法的类,使其实例对象支持迭代操作。

实现原理

  • __iter__() 方法必须返回一个迭代器对象
  • 迭代器对象必须实现 __next__() 方法
  • 每次调用 __iter__() 都应该返回新的迭代器实例

示例:实现一个数字区间可迭代对象

# 自定义迭代器类
class MyRangeIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.end:
            val = self.current
            self.current += 1
            return val
        else:
            raise StopIteration

# 自定义可迭代对象类
class MyRange:
    def __init__(self, start, end):
        self.start = start
        self.end = end
    
    def __iter__(self):
        return MyRangeIterator(self.start, self.end)

# 使用示例
my_range = MyRange(1, 5)
for num in my_range:
    print(num)  # 1, 2, 3, 4

# 可以多次遍历
for num in my_range:
    print(num)  # 1, 2, 3, 4 (重新开始)

设计优势

  • 可重复遍历:每次 for 循环都创建新的迭代器
  • 状态独立:多个迭代器互不影响
  • 内存安全:不会出现状态冲突
  • 符合协议:完全遵循 Python 迭代协议

5.迭代协议详解

5.1.协议定义

迭代协议是 Python 中支持迭代操作的核心机制,包含两个核心方法:

  1. __iter__() - 返回迭代器对象
  2. __next__() - 返回下一个元素,没有时抛出 StopIteration

5.2.协议执行流程

# 1. 调用 iter() 获取迭代器
iterator = iter([1, 2, 3])  # 相当于 iterable.__iter__()

# 2. 循环调用 next() 获取元素
while True:
    try:
        item = next(iterator)  # 相当于 iterator.__next__()
        print(f"获取到元素: {item}")
    except StopIteration:
        print("迭代结束")
        break

5.3.协议层次结构

可迭代对象 (Iterable)
    ↓ 实现 __iter__()
迭代器 (Iterator)
    ↓ 实现 __iter__() 和 __next__()
生成器 (Generator)
    ↓ 自动实现迭代协议

5.4.协议优势

  • 标准化:统一的迭代接口
  • 灵活性:支持自定义迭代行为
  • 效率:惰性计算,按需生成
  • 兼容性:与 Python 内置函数无缝配合

6.迭代器 (Iterator)

6.1.定义和特点

迭代器是实现了 __iter__()__next__() 方法的对象,是迭代协议的核心实现。

核心特征

  • 实现了 __iter__()__next__() 方法
  • 本身也是可迭代对象
  • 状态保持:记住当前位置
  • 一次性使用:遍历完成后不能重新开始
  • 惰性计算:按需生成值

6.2.自定义迭代器

class MyRangeIterator:
    """自定义迭代器示例"""
    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
        current_value = self.current
        self.current += 1
        return current_value

# 使用自定义迭代器
iterator = MyRangeIterator(1, 4)
print(next(iterator))  # 1
print(next(iterator))  # 2
print(next(iterator))  # 3
# print(next(iterator))  # 抛出 StopIteration

6.3.迭代器 vs 可迭代对象

# 列表是可迭代对象,但不是迭代器
lst = [1, 2, 3]
print(hasattr(lst, '__iter__'))  # True
print(hasattr(lst, '__next__'))  # False

# 从列表获取迭代器
lst_iterator = iter(lst)
print(hasattr(lst_iterator, '__iter__'))  # True  
print(hasattr(lst_iterator, '__next__'))  # True

# 验证类型
from collections.abc import Iterator
print(isinstance(lst, Iterator))         # False
print(isinstance(lst_iterator, Iterator)) # True

6.4.迭代器优势

  • 内存效率:不需要预先存储所有数据
  • 惰性计算:按需生成值
  • 状态保持:自动维护迭代状态
  • 一次性使用:避免重复遍历的开销

7.生成器函数 (Generator Function)

7.1.定义和特点

生成器函数是包含 yield 关键字的函数,是创建生成器的主要方式。

核心特征

  • 使用 yield 关键字
  • 调用时返回生成器对象(不立即执行)
  • 保持函数状态,可以多次进入和退出
  • 自动实现迭代协议

7.2.生成器函数示例

def my_generator_function(start, end):
    """生成器函数示例"""
    print("生成器函数开始执行")
    current = start
    while current < end:
        print(f"准备 yield 值: {current}")
        yield current
        print(f"从 yield 恢复执行")
        current += 1
    print("生成器函数执行结束")

# 调用生成器函数返回生成器对象
gen = my_generator_function(1, 4)
print(f"生成器对象: {gen}")  # <generator object my_generator_function at 0x...>

# 使用生成器
for value in gen:
    print(f"主程序获取到: {value}")

7.3.执行流程详解

  1. 第一次调用 next():执行到第一个 yield,返回 yield 的值
  2. 后续调用 next():从上次 yield 处继续执行,到下一个 yield
  3. 函数结束:遇到 return 或函数结束,抛出 StopIteration

7.4.生成器函数优势

  • 状态保持:自动维护函数执行状态
  • 内存效率:按需生成值,节省内存
  • 代码简洁:比自定义迭代器更简洁
  • 协程支持:支持双向通信

8.生成器 (Generator)

8.1.定义和特点

生成器是生成器函数返回的对象,是一种特殊的迭代器。

核心特征

  • 生成器函数返回的对象
  • 特殊的迭代器,自动实现迭代协议
  • 懒加载:按需生成值,节省内存
  • 状态保持:自动维护执行状态
  • 协程支持:支持双向通信

8.2.生成器表达式

# 类似于列表推导式,但返回生成器
numbers = [1, 2, 3, 4, 5]

# 列表推导式 - 立即计算所有值
squares_list = [x**2 for x in numbers]
print(squares_list)  # [1, 4, 9, 16, 25]

# 生成器表达式 - 按需计算
squares_gen = (x**2 for x in numbers)
print(squares_gen)   # <generator object <genexpr> at 0x...>
print(list(squares_gen))  # [1, 4, 9, 16, 25]

8.3.生成器优势

  • 内存效率:按需生成,不预存储所有值
  • 代码简洁:比自定义迭代器更简洁
  • 状态管理:自动维护执行状态
  • 协程支持:支持双向通信和协作式编程

9.总结

9.1.概念对比表

概念定义关键方法特点
可迭代对象实现 __iter__() 的对象__iter__()可被迭代,不保持状态
迭代器实现 __iter__()__next__() 的对象__iter__(), __next__()保持状态,一次性使用
生成器函数包含 yield 的函数-返回生成器,保持函数状态
生成器生成器函数返回的对象__iter__(), __next__()特殊的迭代器,懒加载

9.2.核心关系

可迭代对象 (Iterable)
    ↓ 实现 __iter__()
迭代器 (Iterator)
    ↓ 实现 __iter__() 和 __next__()
生成器 (Generator)
    ↓ 自动实现迭代协议

重要关系

  • 所有生成器都是迭代器
  • 所有迭代器都是可迭代对象
  • 生成器提供了创建迭代器的最简洁方式
  • yield 让 Python 自动实现迭代协议

9.3.选择建议

  • 简单迭代:使用内置可迭代对象(list, tuple, str 等)
  • 复杂逻辑:使用生成器函数
  • 简单转换:使用生成器表达式
  • 自定义行为:实现自定义迭代器类
img