Python 迭代器:从入门到精通

在学 Python 的过程中,我们常常会碰到"迭代器"这个词。它听起来有点抽象,其实本质就是一种"能一个一个取值"的东西。本文就来系统讲讲迭代器,帮你把这个概念吃透。

参考文章:

目录

  1. 什么是可迭代对象(Iterable)?
  2. 什么是迭代器(Iterator)?
  3. iter()next() 的用法
  4. for 循环背后的迭代器机制
  5. 为什么需要迭代器?
  6. 自定义一个迭代器类
  7. 使用生成器简化迭代器
  8. isinstance() 判断是不是迭代器
  9. 可迭代但不是迭代器的对象
  10. 小结和注意事项

1. 什么是可迭代对象(Iterable)?

可迭代对象指的是能被一个个遍历的对象 ,比如列表、字符串、元组、集合、字典等等。判断一个对象是否可迭代,可以用 collections.abc.Iterable 来检查:

python 复制代码
from collections.abc import Iterable

print(isinstance([1, 2, 3], Iterable))  # True
print(isinstance(123, Iterable))       # False

这些对象可以用 for 循环,是因为它们都实现了 __iter__() 方法。


2. 什么是迭代器(Iterator)?

迭代器是一个可以记住当前遍历位置的对象 ,从它那里你可以不停地 next() 出下一个值,直到取不到为止(会抛出 StopIteration 异常)。

一个对象如果:

  • 实现了 __iter__() 方法,返回自身
  • 实现了 __next__() 方法

那它就是一个迭代器。

python 复制代码
from collections.abc import Iterator

print(isinstance(iter([1, 2, 3]), Iterator))  # True

3. iter()next() 的用法

Python 提供了两个内置函数和迭代器打交道:

  • iter(obj):把一个可迭代对象变成迭代器
  • next(iterator):从迭代器里取出下一个值

示例:

python 复制代码
nums = [10, 20, 30]
it = iter(nums)

print(next(it))  # 10
print(next(it))  # 20
print(next(it))  # 30
# print(next(it))  # 报错:StopIteration

4. for 循环背后的迭代器机制

你用惯的 for 循环,其实背后就是在用迭代器。来看下"真相":

python 复制代码
for x in [1, 2, 3]:
    print(x)

其实等价于:

python 复制代码
it = iter([1, 2, 3])
while True:
    try:
        x = next(it)
        print(x)
    except StopIteration:
        break

是不是瞬间明白了?


5. 为什么需要迭代器?

迭代器有两个大优点:

  • 惰性计算:只有在需要下一个值的时候才去计算,节省内存
  • 适合处理大型数据流:比如处理几百 GB 的日志文件时,就不能一次性全部加载到内存中,这时候迭代器就派上用场了

6. 自定义一个迭代器类

我们可以自定义一个类来模拟迭代器的行为,比如实现一个生成斐波那契数列的迭代器:

python 复制代码
class Fibonacci:
    def __init__(self, max):
        self.max = max
        self.a = 0
        self.b = 1

    def __iter__(self):
        return self

    def __next__(self):
        if self.a > self.max:
            raise StopIteration
        value = self.a
        self.a, self.b = self.b, self.a + self.b
        return value

fib = Fibonacci(100)
for num in fib:
    print(num, end=' ')

输出:0 1 1 2 3 5 8 13 21 34 55 89


7. 使用生成器简化迭代器

虽然可以用类实现迭代器,但有时候写起来太麻烦。Python 提供了更简洁的方式:生成器(generator)

yield 写个斐波那契生成器:

python 复制代码
def fibonacci(max):
    a, b = 0, 1
    while a <= max:
        yield a
        a, b = b, a + b

for n in fibonacci(100):
    print(n, end=' ')

是不是比类清爽多了?


8. isinstance() 判断是不是迭代器

快速判断对象的类型是否是可迭代或迭代器:

python 复制代码
from collections.abc import Iterable, Iterator

print(isinstance([1, 2, 3], Iterable))  # True
print(isinstance([1, 2, 3], Iterator))  # False

it = iter([1, 2, 3])
print(isinstance(it, Iterator))        # True

9. 可迭代但不是迭代器的对象

很多常见的结构(比如 list、str)是"可迭代的",但它们不是"迭代器":

python 复制代码
lst = [1, 2, 3]
print(hasattr(lst, '__iter__'))   # True
print(hasattr(lst, '__next__'))   # False

不过你可以随时把它变成迭代器:

python 复制代码
it = iter(lst)
print(next(it))  # 1

10. 小结

  • 所有能被 for 遍历的都是"可迭代对象"
  • 迭代器是"可迭代对象"的一种升级版,它支持 next()、惰性计算
  • 自定义迭代器要写 __iter__()__next__() 方法
  • 想省事就用生成器 yield,写起来又简洁又优雅
  • 一定要注意 StopIteration,它是控制"结束"的信号
相关推荐
肖永威19 分钟前
macOS环境安装/卸载python实践笔记
笔记·python·macos
TechWJ35 分钟前
PyPTO编程范式深度解读:让NPU开发像写Python一样简单
开发语言·python·cann·pypto
枷锁—sha42 分钟前
【SRC】SQL注入WAF 绕过应对策略(二)
网络·数据库·python·sql·安全·网络安全
abluckyboy1 小时前
Java 实现求 n 的 n^n 次方的最后一位数字
java·python·算法
喵手1 小时前
Python爬虫实战:构建各地统计局数据发布板块的自动化索引爬虫(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·采集数据csv导出·采集各地统计局数据发布数据·统计局数据采集
天天爱吃肉82182 小时前
跟着创意天才周杰伦学新能源汽车研发测试!3年从工程师到领域专家的成长秘籍!
数据库·python·算法·分类·汽车
m0_715575342 小时前
使用PyTorch构建你的第一个神经网络
jvm·数据库·python
甄心爱学习2 小时前
【leetcode】判断平衡二叉树
python·算法·leetcode
深蓝电商API2 小时前
滑块验证码破解思路与常见绕过方法
爬虫·python
Ulyanov2 小时前
Pymunk物理引擎深度解析:从入门到实战的2D物理模拟全攻略
python·游戏开发·pygame·物理引擎·pymunk