第75集:迭代器与可迭代对象
学习目标
- 理解迭代器(Iterator)的概念
- 理解可迭代对象(Iterable)的概念
- 掌握迭代器和可迭代对象的区别
- 学会创建自定义迭代器
- 理解迭代协议的工作原理
- 掌握iter()和next()函数的使用
什么是可迭代对象
可迭代对象(Iterable)是指可以逐个访问其元素的对象。在Python中,任何实现了__iter__()方法的对象都是可迭代对象。
常见的可迭代对象
- 列表(list)
- 元组(tuple)
- 字符串(str)
- 字典(dict)
- 集合(set)
- 文件对象
- 生成器
可迭代对象的特点
- 可以使用for循环遍历
- 可以传递给iter()函数
- 可以用于解包操作
什么是迭代器
迭代器(Iterator)是一个实现了迭代协议的对象,可以记住遍历的位置。迭代器实现了两个方法:
__iter__(): 返回迭代器对象本身__next__(): 返回下一个元素,如果没有元素则抛出StopIteration异常
迭代器的特点
- 可以逐个访问元素
- 记住当前遍历位置
- 只能向前遍历,不能后退
- 遍历一次后即耗尽
迭代协议
迭代协议是Python中定义对象如何迭代的规范。
协议内容
- 可迭代对象必须实现
__iter__()方法 - 迭代器必须实现
__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的迭代机制,并能够创建自定义的可迭代对象和迭代器。