当前位置:首页>python>Python面向对象(七):迭代器与生成器——让对象"可遍历"的魔法

Python面向对象(七):迭代器与生成器——让对象"可遍历"的魔法

  • 2026-10-11 06:37:54
Python面向对象(七):迭代器与生成器——让对象"可遍历"的魔法
for 循环看起来简单,背后却有一套完整的协议在支撑。理解它,你就能让任何自定义对象都能被 for 遍历。

迭代器协议:for 循环的底层原理

Python 中的迭代协议只要求两个方法:

classMyIterator:def__iter__(self):returnself# 返回迭代器本身def__next__(self):# 返回下一个值,没有时抛出 StopIteration        ...

for 循环的本质就是:

  1. 调用 __iter__() 获取迭代器
  2. 反复调用 __next__() 获取下一个值
  3. 遇到 StopIteration 时停止

手动实现一个迭代器

classCountdown:def__init__(self, start):self.current = startdef__iter__(self):returnselfdef__next__(self):ifself.current <= 0:raise StopIteration        value = self.currentself.current -= 1return valuefor n in Countdown(5):print(n)# 5, 4, 3, 2, 1

这就是一个倒计时迭代器。每次 __next__ 返回当前值并减1,到0时抛出 StopIteration 结束。

生成器:更简单的迭代器

写 __iter__ 和 __next__ 有点麻烦?用 yield 关键字:

defcountdown(start):    current = startwhile current > 0:yield current      # 暂停并返回当前值        current -= 1for n in countdown(5):print(n)# 5, 4, 3, 2, 1

yield 让函数变成生成器——它自动实现了 __iter__ 和 __next__,代码量减少一半。

yield 的工作原理

defsimple_gen():print("开始")yield1print("继续")yield2print("结束")g = simple_gen()  # 此时函数还没执行!print(next(g))    # 输出"开始",返回 1print(next(g))    # 输出"继续",返回 2print(next(g))    # 输出"结束",抛出 StopIteration

关键点:

  • 调用生成器函数时不执行,只返回一个生成器对象
  • 每次 next() 执行到下一个 yield 处暂停
  • 函数内的局部变量状态被保留

让自定义对象可遍历

classTeam:def__init__(self):self.members = ["Alice", "Bob", "Charlie"]def__iter__(self):returniter(self.members)# 或者用生成器:# for member in self.members:#     yield memberteam = Team()for person in team:print(person)# Alice, Bob, Charlie

只需要实现 __iter__,返回一个迭代器即可。

生成器表达式

类似列表推导式,但用圆括号,按需生成不占内存:

# 列表推导式:一次性生成所有值squares_list = [x*x for x inrange(1000000)]  # 占用大量内存# 生成器表达式:每次只生成一个值squares_gen = (x*x for x inrange(1000000))   # 几乎不占内存print(next(squares_gen))  # 0print(next(squares_gen))  # 1print(next(squares_gen))  # 4

生成器的进阶用法

无限序列

deffibonacci():    a, b = 0, 1whileTrue:yield a        a, b = b, a + bfib = fibonacci()for _ inrange(10):print(next(fib), end=" ")# 0 1 1 2 3 5 8 13 21 34

管道式处理

defread_lines(filename):withopen(filename) as f:for line in f:yield line.strip()deffilter_empty(lines):for line in lines:if line:yield linedefto_upper(lines):for line in lines:yield line.upper()# 链式处理,每一步都是惰性求值pipeline = to_upper(filter_empty(read_lines("data.txt")))for line in pipeline:print(line)

小结

概念
说明
__iter__
返回迭代器对象
__next__
返回下一个值,结束时抛出 StopIteration
yield
让函数变成生成器,自动实现迭代协议
生成器表达式
(x for x in range(10))
,惰性求值省内存
核心优势
惰性计算、节省内存、代码简洁

💡 练习:写一个 range2(start, stop, step) 生成器,模拟内置 range() 的功能。

最新文章

随机文章