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,它是控制"结束"的信号
相关推荐
databook10 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar11 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805111 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_11 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机18 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机19 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机19 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机19 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i19 小时前
drf初步梳理
python·django
每日AI新事件19 小时前
python的异步函数
python