欢迎光临
我们一直在努力

Python 中的迭代器

   迭代器是 Python 中实现迭代协议的对象,允许你逐个访问容器中的元素,而无需提前知道容器的内部结构。迭代器是 Python 实现 for 循环的基础。

一、迭代器

迭代器是一个实现了迭代器协议的对象,即实现了 __iter__() 和 __next__() 方法。

方法作用
__iter__() 返回迭代器对象本身
__next__() 返回下一个元素,没有元素时抛出 StopIteration

可迭代对象 vs 迭代器

# 可迭代对象(Iterable):实现了 __iter__() 方法
# 迭代器(Iterator):同时实现了 __iter__() 和 __next__() 方法

# 列表是可迭代对象,不是迭代器
my_list = [1, 2, 3]
print(dir(my_list)) # 有 __iter__,没有 __next__

# 获取迭代器
iterator = iter(my_list)
print(dir(iterator)) # 有 __iter__ 和 __next__

# 手动迭代
print(next(iterator)) # 1
print(next(iterator)) # 2
print(next(iterator)) # 3
# print(next(iterator)) # StopIteration

二、迭代器的基本使用

1. 手动迭代

# 使用 iter() 和 next()
colors = ['red', 'green', 'blue']
iterator = iter(colors)

print(next(iterator)) # red
print(next(iterator)) # green
print(next(iterator)) # blue
# print(next(iterator)) # StopIteration

2. 使用 for 循环自动迭代

# for 循环内部自动调用 iter() 和 next()
for color in colors:
print(color)
# 等价于:
iterator = iter(colors)
while True:
try:
color = next(iterator)
print(color)
except StopIteration:
break

3. 检测是否可迭代

from collections.abc import Iterable, Iterator

# 判断是否可迭代
print(isinstance([1, 2, 3], Iterable)) # True
print(isinstance(123, Iterable)) # False

# 判断是否是迭代器
print(isinstance(iter([1, 2, 3]), Iterator)) # True
print(isinstance([1, 2, 3], Iterator)) # False

三、自定义迭代器

1. 实现迭代器协议

class MyRange:
"""自定义一个类似 range 的迭代器"""
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
value = self.current
self.current += 1
return value

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

# 也可以手动迭代
mr = MyRange(1, 3)
print(next(mr)) # 1
print(next(mr)) # 2

2. 斐波那契数列迭代器

class Fibonacci:
"""斐波那契数列迭代器"""
def __init__(self, max_count):
self.max_count = max_count
self.count = 0
self.a = 0
self.b = 1

def __iter__(self):
return self

def __next__(self):
if self.count >= self.max_count:
raise StopIteration

if self.count == 0:
self.count += 1
return self.a
elif self.count == 1:
self.count += 1
return self.b

self.a, self.b = self.b, self.a + self.b
self.count += 1
return self.b

for num in Fibonacci(10):
print(num, end=' ') # 0 1 1 2 3 5 8 13 21 34

四、内置迭代器工具

1. enumerate – 带索引的迭代

fruits = ['apple', 'banana', 'orange']

# enumerate 返回迭代器,产生 (index, value) 元组
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")

# 指定起始索引
for i, fruit in enumerate(fruits, start=1):
print(f"{i}: {fruit}")

2. zip – 并行迭代

names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
scores = [85, 92, 78]

# zip 返回迭代器,产生元组
for name, age, score in zip(names, ages, scores):
print(f"{name}, {age}岁, {score}分")

# 转换为列表
pairs = list(zip(names, ages))
print(pairs) # [('Alice', 25), ('Bob', 30), ('Charlie', 35)]

3. map – 映射迭代

numbers = [1, 2, 3, 4, 5]

# map 返回迭代器
squares = map(lambda x: x ** 2, numbers)
print(list(squares)) # [1, 4, 9, 16, 25]

# 多个序列
a = [1, 2, 3]
b = [10, 20, 30]
sums = map(lambda x, y: x + y, a, b)
print(list(sums)) # [11, 22, 33]

4. filter – 过滤迭代

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# filter 返回迭代器,只保留满足条件的元素
even = filter(lambda x: x % 2 == 0, numbers)
print(list(even)) # [2, 4, 6, 8, 10]

# 等价于列表推导式
even = [x for x in numbers if x % 2 == 0]

5. itertools 模块

import itertools

# 无限迭代器
counter = itertools.count(start=1, step=2) # 1, 3, 5, 7, …
for i, val in zip(range(5), counter):
print(val, end=' ') # 1 3 5 7 9

# 循环迭代器
cycle = itertools.cycle(['A', 'B', 'C'])
for i, val in zip(range(6), cycle):
print(val, end=' ') # A B C A B C

# 排列组合
perms = itertools.permutations([1, 2, 3], 2)
print(list(perms)) # [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)]

combs = itertools.combinations([1, 2, 3], 2)
print(list(combs)) # [(1,2), (1,3), (2,3)]

五、迭代器的优势

1. 惰性求值(节省内存)

# 传统方式:一次性生成所有数据,占用大量内存
def get_numbers_traditional(n):
result = []
for i in range(n):
result.append(i ** 2)
return result

# 迭代器方式:逐个生成,节省内存
def get_numbers_iterative(n):
for i in range(n):
yield i ** 2 # 生成器函数返回迭代器

# 处理大规模数据
traditional = get_numbers_traditional(1000000) # 占用大量内存
iterative = get_numbers_iterative(1000000) # 几乎不占内存

2. 处理无限序列

# 迭代器可以表示无限序列
def infinite_numbers():
n = 0
while True:
yield n
n += 1

# 只取前 10 个
for num in infinite_numbers():
if num >= 10:
break
print(num, end=' ') # 0 1 2 3 4 5 6 7 8 9

3. 单次遍历

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

print(list(iterator)) # [1, 2, 3]
print(list(iterator)) # [](迭代器已耗尽)

六、迭代器 vs 序列对比

特性序列(list, tuple)迭代器(Iterator)
内存占用 大(存储所有元素) 小(一次只存一个)
访问方式 随机访问(索引) 顺序访问(next)
遍历次数 可多次遍历 只能遍历一次
无限序列 不支持 支持
适用场景 数据量小、需要随机访问 数据量大、只需遍历一次

七、常见错误

1. 迭代器一次性

numbers = [1, 2, 3]
it = iter(numbers)

print(sum(it)) # 6
print(sum(it)) # 0(迭代器已耗尽)

# 解决方案:重新创建迭代器
it = iter(numbers)
print(list(it)) # [1, 2, 3]

2. 修改容器时迭代

# 错误:迭代时修改容器
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # 可能导致跳过元素
print(numbers) # [1, 3, 5](看似正确,但行为不确定)

# 正确:迭代副本
for num in numbers[:]: # 使用切片副本
if num % 2 == 0:
numbers.remove(num)

# 正确:使用列表推导式
numbers = [num for num in numbers if num % 2 != 0]

八、生成器:迭代器的简便实现

生成器是使用 yield 关键字创建迭代器的简便方式。

# 生成器函数
def my_range(n):
i = 0
while i < n:
yield i
i += 1

for num in my_range(5):
print(num, end=' ') # 0 1 2 3 4

# 生成器表达式
squares = (x ** 2 for x in range(10))
print(type(squares)) # <class 'generator'>

# 生成器与列表推导式的区别
list_comp = [x ** 2 for x in range(10)] # 列表(立即计算)
gen_exp = (x ** 2 for x in range(10)) # 生成器(惰性计算)

其他

概念关键方法特点
可迭代对象 __iter__() 可以被 iter() 转换为迭代器
迭代器 __iter__() + __next__() 支持 next() 调用
生成器 yield 用函数语法创建迭代器
生成器表达式 (x for x in …) 类似列表推导式,惰性求值

核心要点:

  • 迭代器通过 __iter__ 和 __next__ 实现

  • for 循环自动处理迭代器的 StopIteration

  • 迭代器惰性求值,节省内存

  • 迭代器只能遍历一次

  • 生成器是创建迭代器的简便方式

  • 赞(0)
    未经允许不得转载:171主机测评 » Python 中的迭代器
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址