第75集:迭代器与可迭代对象

学习目标

  • 理解迭代器(Iterator)的概念
  • 理解可迭代对象(Iterable)的概念
  • 掌握迭代器和可迭代对象的区别
  • 学会创建自定义迭代器
  • 理解迭代协议的工作原理
  • 掌握iter()和next()函数的使用

什么是可迭代对象

可迭代对象(Iterable)是指可以逐个访问其元素的对象。在Python中,任何实现了__iter__()方法的对象都是可迭代对象。

常见的可迭代对象

  • 列表(list)
  • 元组(tuple)
  • 字符串(str)
  • 字典(dict)
  • 集合(set)
  • 文件对象
  • 生成器

可迭代对象的特点

  • 可以使用for循环遍历
  • 可以传递给iter()函数
  • 可以用于解包操作

什么是迭代器

迭代器(Iterator)是一个实现了迭代协议的对象,可以记住遍历的位置。迭代器实现了两个方法:

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

迭代器的特点

  • 可以逐个访问元素
  • 记住当前遍历位置
  • 只能向前遍历,不能后退
  • 遍历一次后即耗尽

迭代协议

迭代协议是Python中定义对象如何迭代的规范。

协议内容

  1. 可迭代对象必须实现__iter__()方法
  2. 迭代器必须实现__iter__()__next__()方法

工作流程

# 1. 从可迭代对象获取迭代器
iterable = [1, 2, 3]
iterator = iter(iterable)

# 2. 使用next()获取元素
element = next(iterator)  # 1
element = next(iterator)  # 2
element = next(iterator)  # 3

# 3. 没有更多元素时抛出StopIteration
element = next(iterator)  # StopIteration

基本示例

示例1:使用iter()和next()

# 创建可迭代对象
my_list = [1, 2, 3, 4, 5]

# 获取迭代器
my_iterator = iter(my_list)

# 使用next()获取元素
print(next(my_iterator))  # 1
print(next(my_iterator))  # 2
print(next(my_iterator))  # 3

示例2:for循环的内部机制

# for循环实际上是使用迭代器
my_list = [1, 2, 3]

# for循环等价于:
iterator = iter(my_list)
while True:
    try:
        element = next(iterator)
        print(element)
    except StopIteration:
        break

示例3:检查对象是否可迭代

from collections.abc import Iterable

# 检查对象是否可迭代
print(isinstance([1, 2, 3], Iterable))  # True
print(isinstance("hello", Iterable))  # True
print(isinstance(123, Iterable))  # False
print(isinstance({"a": 1}, Iterable))  # True

迭代器 vs 可迭代对象

区别对比

# 可迭代对象
my_list = [1, 2, 3]
print(type(my_list))  # <class 'list'>
print(hasattr(my_list, '__iter__'))  # True

# 迭代器
my_iterator = iter(my_list)
print(type(my_iterator))  # <class 'list_iterator'>
print(hasattr(my_iterator, '__iter__'))  # True
print(hasattr(my_iterator, '__next__'))  # True

关键区别

特性 可迭代对象 迭代器
__iter__()
__next__()
可重复遍历
记住位置

创建自定义迭代器

示例4:基本迭代器

class MyIterator:
    """自定义迭代器"""
    
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        """返回迭代器对象本身"""
        return self
    
    def __next__(self):
        """返回下一个元素"""
        if self.index >= len(self.data):
            raise StopIteration
        result = self.data[self.index]
        self.index += 1
        return result

# 使用自定义迭代器
my_iter = MyIterator([1, 2, 3])
for item in my_iter:
    print(item)

示例5:计数器迭代器

class Counter:
    """计数器迭代器"""
    
    def __init__(self, start=0, end=10):
        self.current = start
        self.end = end
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current > self.end:
            raise StopIteration
        result = self.current
        self.current += 1
        return result

# 使用计数器
counter = Counter(1, 5)
for num in counter:
    print(num)

示例6:斐波那契数列迭代器

class Fibonacci:
    """斐波那契数列迭代器"""
    
    def __init__(self, n):
        self.n = n
        self.count = 0
        self.a, self.b = 0, 1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.count >= self.n:
            raise StopIteration
        result = self.a
        self.a, self.b = self.b, self.a + self.b
        self.count += 1
        return result

# 使用斐波那契迭代器
fib = Fibonacci(10)
for num in fib:
    print(num)

创建自定义可迭代对象

示例7:可迭代对象

class MyIterable:
    """自定义可迭代对象"""
    
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        """返回迭代器"""
        return MyIterator(self.data)

class MyIterator:
    """迭代器"""
    
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        result = self.data[self.index]
        self.index += 1
        return result

# 使用自定义可迭代对象
my_iterable = MyIterable([1, 2, 3])
for item in my_iterable:
    print(item)

# 可以多次遍历
for item in my_iterable:
    print(item)

示例8:范围可迭代对象

class MyRange:
    """自定义范围类"""
    
    def __init__(self, start, end=None, step=1):
        if end is None:
            self.start = 0
            self.end = start
        else:
            self.start = start
            self.end = end
        self.step = step
    
    def __iter__(self):
        return MyRangeIterator(self.start, self.end, self.step)

class MyRangeIterator:
    """范围迭代器"""
    
    def __init__(self, start, end, step):
        self.current = start
        self.end = end
        self.step = step
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.step > 0 and self.current >= self.end:
            raise StopIteration
        if self.step < 0 and self.current <= self.end:
            raise StopIteration
        result = self.current
        self.current += self.step
        return result

# 使用自定义范围
for i in MyRange(5):
    print(i)  # 0, 1, 2, 3, 4

for i in MyRange(1, 10, 2):
    print(i)  # 1, 3, 5, 7, 9

迭代器的应用

应用1:逐行读取文件

class FileLineReader:
    """逐行读取文件的迭代器"""
    
    def __init__(self, filename):
        self.filename = filename
        self.file = None
    
    def __iter__(self):
        self.file = open(self.filename, 'r', encoding='utf-8')
        return self
    
    def __next__(self):
        line = self.file.readline()
        if not line:
            self.file.close()
            raise StopIteration
        return line.strip()

# 使用文件行迭代器
for line in FileLineReader('example.txt'):
    print(line)

应用2:无限序列

class InfiniteCounter:
    """无限计数器"""
    
    def __init__(self, start=0):
        self.current = start
    
    def __iter__(self):
        return self
    
    def __next__(self):
        result = self.current
        self.current += 1
        return result

# 使用无限计数器(需要手动停止)
counter = InfiniteCounter()
for i, num in enumerate(counter):
    print(num)
    if i >= 10:  # 只打印前11个
        break

应用3:数据流处理

class DataStream:
    """数据流迭代器"""
    
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        result = self.process(self.data[self.index])
        self.index += 1
        return result
    
    def process(self, item):
        """处理数据"""
        return item * 2

# 使用数据流
stream = DataStream([1, 2, 3, 4, 5])
for item in stream:
    print(item)

迭代器的限制

限制1:只能遍历一次

my_list = [1, 2, 3]
iterator = iter(my_list)

# 第一次遍历
for item in iterator:
    print(item)

# 第二次遍历 - 不会输出
for item in iterator:
    print(item)

限制2:不能回退

my_list = [1, 2, 3]
iterator = iter(my_list)

next(iterator)  # 1
next(iterator)  # 2
# 无法回到第一个元素

限制3:不能随机访问

my_list = [1, 2, 3]
iterator = iter(my_list)

# 不能通过索引访问
# iterator[0]  # TypeError

最佳实践

实践1:分离可迭代对象和迭代器

# 推荐:分离可迭代对象和迭代器
class MyCollection:
    def __init__(self, data):
        self.data = data
    
    def __iter__(self):
        return MyIterator(self.data)

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        result = self.data[self.index]
        self.index += 1
        return result

实践2:使用生成器简化迭代器

# 推荐:使用生成器创建迭代器
def my_generator(data):
    for item in data:
        yield item

# 使用生成器
for item in my_generator([1, 2, 3]):
    print(item)

实践3:正确处理StopIteration

# 推荐:正确处理StopIteration
def safe_next(iterator, default=None):
    """安全获取下一个元素"""
    try:
        return next(iterator)
    except StopIteration:
        return default

my_list = [1, 2, 3]
iterator = iter(my_list)

print(safe_next(iterator))  # 1
print(safe_next(iterator))  # 2
print(safe_next(iterator))  # 3
print(safe_next(iterator))  # None

实践4:使用iter()函数

# 推荐:使用iter()函数获取迭代器
my_list = [1, 2, 3]
iterator = iter(my_list)

# 而不是直接调用__iter__()
# iterator = my_list.__iter__()

常见错误

错误1:混淆迭代器和可迭代对象

my_list = [1, 2, 3]

# 错误:对可迭代对象调用next()
# next(my_list)  # TypeError: 'list' object is not an iterator

# 正确:先获取迭代器
iterator = iter(my_list)
next(iterator)  # 1

错误2:忘记实现__iter__()方法

# 错误:忘记实现__iter__()方法
class BadIterable:
    def __init__(self, data):
        self.data = data

# 不能用于for循环
# for item in BadIterable([1, 2, 3]):
#     print(item)  # TypeError: 'BadIterable' object is not iterable

错误3:忘记抛出StopIteration

# 错误:忘记抛出StopIteration
class InfiniteIterator:
    def __init__(self):
        self.current = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        result = self.current
        self.current += 1
        return result  # 永远不会停止

# 正确:应该抛出StopIteration
class CorrectIterator:
    def __init__(self, n):
        self.current = 0
        self.n = n
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current >= self.n:
            raise StopIteration
        result = self.current
        self.current += 1
        return result

总结

迭代器和可迭代对象是Python中重要的概念,理解它们对于掌握Python的迭代机制至关重要。

核心概念

  • 可迭代对象:实现了__iter__()方法,可以获取迭代器
  • 迭代器:实现了__iter__()__next__()方法,可以逐个访问元素
  • 迭代协议:定义了对象如何迭代的规范

关键区别

  • 可迭代对象可以重复遍历,迭代器只能遍历一次
  • 迭代器记住遍历位置,可迭代对象不记住
  • 所有迭代器都是可迭代对象,但不是所有可迭代对象都是迭代器

应用场景

  • 自定义数据结构
  • 流式数据处理
  • 无限序列
  • 文件处理

掌握迭代器和可迭代对象的概念,将帮助你更好地理解Python的迭代机制,并能够创建自定义的可迭代对象和迭代器。

« 上一篇 生成器表达式 下一篇 » 生成器函数