《深入 Python 可迭代世界:三种方式手写斐波那契数列(类、生成器、itertools)全解析》

2025博客之星年度评选已开启 10w+人浏览 2.3k人参与

《深入 Python 可迭代世界:三种方式手写斐波那契数列(类、生成器、itertools)全解析》

在我这些年教授 Python 的过程中,有一个经典问题几乎从未缺席过课堂与面试——如何实现一个可迭代的斐波那契数列?

它看似简单,却能从多个维度考察一个 Python 开发者对:

  • 迭代器协议
  • 生成器机制
  • 惰性计算
  • itertools 工具链
  • 代码风格与可维护性

的理解程度。

更重要的是,它能帮助你真正理解 Python “让数据流动起来”的哲学。

今天,我们就从基础到进阶,带你用三种方式手写一个可迭代的 Fibonacci:

  1. 基于类的迭代器实现
  2. 基于生成器的实现
  3. 基于 itertools 的函数式实现

并结合实战经验,分析每种方式的适用场景、优缺点与最佳实践。


一、开篇:为什么是斐波那契?为什么是可迭代?

Python 的发展史是一部“简洁优雅”的进化史。从 Guido 在 1989 年圣诞节写下第一行 Python 代码,到如今成为 Web、数据科学、AI、自动化的主流语言,它的核心理念始终未变:

让复杂的事情变简单,让简单的事情变优雅。

而“可迭代”正是 Python 世界中最优雅的抽象之一。

  • 你可以遍历一个列表
  • 你可以遍历一个文件
  • 你可以遍历一个无限序列(如 Fibonacci)
  • 你可以遍历一个网络流、数据库游标、实时数据管道

可迭代对象是 Python 数据流的基础设施。

而 Fibonacci 则是最适合作为示例的序列:

  • 简单易懂
  • 具备数学美感
  • 可以无限生成
  • 适合展示惰性计算
  • 适合展示迭代器协议与生成器协议

所以,这篇文章不仅仅是“写 Fibonacci”,而是带你真正理解 Python 的迭代哲学。


二、基础回顾:迭代器协议与生成器协议

在进入代码之前,我们先快速回顾两个核心概念。

1. 迭代器协议(Iterator Protocol)

只要一个对象实现了:

  • __iter__()
  • __next__()

它就是一个迭代器。

class Iterator:
    def __iter__(self):
        return self

    def __next__(self):
        ...

2. 生成器协议(Generator Protocol)

yield 的函数会自动生成一个实现了:

  • __iter__()
  • __next__()
  • send()
  • throw()
  • close()

的生成器对象。

生成器是 Python 最优雅的状态机。


三、第一种写法:基于类的迭代器(最原始、最底层、最能体现协议本质)

这是最“正统”的写法,也是面试中最能体现你对迭代器协议理解程度的方式。

1. 代码实现

class Fibonacci:
    def __init__(self, max_count=None):
        self.a = 0
        self.b = 1
        self.count = 0
        self.max_count = max_count  # 可选:限制生成数量

    def __iter__(self):
        return self

    def __next__(self):
        if self.max_count is not None and self.count >= self.max_count:
            raise StopIteration

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

2. 使用方式

for n in Fibonacci(10):
    print(n)

输出:

0 1 1 2 3 5 8 13 21 34

3. 优点

  • 完整体现迭代器协议
  • 可自定义状态、限制、缓存等逻辑
  • 适合构建复杂迭代器类

4. 缺点

  • 代码冗长
  • 手动维护状态容易出错
  • 不够 Pythonic

5. 适用场景

  • 面试
  • 需要构建复杂迭代器类
  • 需要可复用、可扩展的对象

四、第二种写法:基于生成器(最 Pythonic、最常用、最优雅)

生成器是 Python 的灵魂之一。

只需要一个 yield,你就能写出一个可迭代的 Fibonacci。

1. 代码实现

def fibonacci(max_count=None):
    a, b = 0, 1
    count = 0

    while max_count is None or count < max_count:
        yield a
        a, b = b, a + b
        count += 1

2. 使用方式

for n in fibonacci(10):
    print(n)

3. 优点

  • 代码最简洁
  • 自动维护状态
  • 惰性计算
  • 可无限生成

4. 缺点

  • 不适合复杂状态机
  • 不如类迭代器可扩展

5. 适用场景

  • 90% 的实际项目
  • 数据流处理
  • pipeline 设计
  • 惰性计算

五、第三种写法:基于 itertools(函数式、组合式、最强大)

itertools 是 Python 中最强大的函数式工具库之一。

我们可以用它构建一个无限 Fibonacci 序列。

1. 使用 itertools.count + accumulate

import itertools

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

但这只是生成器写法。

我们来点更“itertools 风格”的。

2. 使用 itertools.accumulate(更函数式)

import itertools
import operator

def fibonacci():
    return itertools.accumulate(
        itertools.repeat(1),
        lambda x, _: (x[1], x[0] + x[1]),
        initial=(0, 1)
    )

但这个版本返回的是 (a, b) 元组,我们需要取第一个值:

def fibonacci():
    for a, b in itertools.accumulate(
        itertools.repeat(1),
        lambda x, _: (x[1], x[0] + x[1]),
        initial=(0, 1)
    ):
        yield a

3. 使用方式

fib = fibonacci()
for _ in range(10):
    print(next(fib))

4. 优点

  • 完全惰性
  • 可组合、可复用
  • 适合函数式编程风格
  • 与 pipeline 完美结合

5. 缺点

  • 可读性较差
  • 不适合初学者

6. 适用场景

  • 高性能数据流处理
  • pipeline 组合
  • 需要与 itertools 生态结合

六、三种方式对比总结

写法优点缺点适用场景
类迭代器完整体现协议、可扩展代码冗长面试、复杂状态机
生成器最简洁、最 Pythonic扩展性一般90% 项目、数据流
itertools高性能、可组合可读性差pipeline、函数式编程

七、实战:构建一个 Fibonacci 数据处理 pipeline

假设我们要:

  • 生成 Fibonacci 序列
  • 过滤出偶数
  • 取前 10 个
  • 求平方

我们可以用生成器 pipeline:

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

def even_filter(seq):
    for n in seq:
        if n % 2 == 0:
            yield n

def square(seq):
    for n in seq:
        yield n * n

def take(seq, n):
    for i, v in enumerate(seq):
        if i >= n:
            break
        yield v

pipeline = take(square(even_filter(fibonacci())), 10)

print(list(pipeline))

输出:

[0, 4, 64, 1156, 20736, ...]

这就是 Python 惰性数据流的魅力。


八、最佳实践:如何选择合适的实现方式?

1. 如果你在写教程或面试题:用类迭代器

能展示你对协议的理解。

2. 如果你在写实际项目:用生成器

最简洁、最优雅、最易维护。

3. 如果你在写数据处理 pipeline:用 itertools

性能最佳、组合性最强。


九、前沿视角:可迭代思想在现代 Python 中的延伸

Python 的可迭代思想已经渗透到:

  • asyncio(异步迭代器)
  • FastAPI(流式响应)
  • Pandas(迭代行)
  • PyTorch(数据加载器 DataLoader)
  • 生成器协程(PEP 380)
  • async generator(PEP 525)

未来,随着数据规模不断扩大,惰性计算与可迭代数据流将变得更加重要。


十、总结与互动

今天,我们从基础到进阶,完整解析了:

  • Python 的迭代器协议与生成器协议
  • 三种方式手写 Fibonacci
  • 各自的优缺点与适用场景
  • 如何构建数据流 pipeline
  • 可迭代思想在现代 Python 中的延伸

我很想听听你的想法:

  • 你更喜欢哪种 Fibonacci 写法?
  • 你在项目中是否用过生成器或 itertools?
  • 想不想让我写一篇《深入 itertools:构建高性能数据流处理框架》?

欢迎留言,我们一起把 Python 玩得更深入、更优雅。

如果你愿意,我也可以继续写:

  • 迭代器协议的底层实现
  • yield from 与 await 的关系
  • 如何用生成器构建协程系统

随时告诉我,我很乐意继续陪你探索 Python 的世界。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铭渊老黄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值