Python迭代器与生成器精讲之大幅降低内存占用

 更新时间:2026年06月11日 08:59:08   作者:二月龙  
生成器本质上也是一种迭代器,是一种特殊的迭代器,这篇文章主要介绍了Python迭代器与生成器精讲之大幅降低内存占用的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

处理大规模数据时,内存往往是第一道瓶颈。列表一次要把所有数据加载进内存,100 万条记录可能直接吃掉几百 MB。迭代器和生成器,就是 Python 给你的省内存利器

一、先搞清:什么是可迭代对象

能被 for 循环遍历的,都叫可迭代对象(Iterable)

python
list, tuple, str, dict, set  → 都是可迭代对象

但可迭代 ≠ 迭代器。

二、迭代器(Iterator):边用边取,用完即丢

迭代器是一个记住了当前位置的对象,每次只返回一个值,取完就没了。

python
it = iter([1, 2, 3])
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # StopIteration ← 取完了

关键特性

特性说明
__iter__() 方法返回自己
__next__() 方法返回下一个值,没有则抛 StopIteration
只能前进,不能回退像磁带,不能倒带
只能遍历一次读完就空了

列表是可迭代对象,但不是迭代器:

python
lst = [1, 2, 3]
hasattr(lst, '__next__')  # False

it = iter(lst)
hasattr(it, '__next__')   # True ← 这才是迭代器

for 循环的本质,就是不断调用 next(),直到捕获 StopIteration

三、生成器(Generator):写起来像函数,用起来像迭代器

生成器是一种特殊的迭代器,不用写类,用 yield 就能造出来。

1. 生成器函数

python
def count_up_to(n):
    i = 1
    while i <= n:
        yield i      # 暂停,返回 i,下次从这里继续
        i += 1

gen = count_up_to(5)
print(next(gen))  # 1
print(next(gen))  # 2

yieldreturn 的区别:

returnyield
执行后函数结束,局部变量销毁暂停,局部变量保留
调用次数一次可以多次 resume
返回值一个结果每次返回一个值

2. 生成器表达式

语法和列表推导式一样,只是把 [] 换成 ()

python
# 列表推导式 → 一次性生成所有数据,占内存
squares_list = [x**2 for x in range(1000000)]   # ~40 MB

# 生成器表达式 → 用一个取一个,几乎不占内存
squares_gen = (x**2 for x in range(1000000))    # ~几十字节

四、内存对比:数据说话

处理 1000 万个整数的平方:

方式内存占用说明
列表 [x**2 for x in range(10_000_000)]~80 MB全部加载进内存
生成器 (x**2 for x in range(10_000_000))~120 字节只存当前状态
迭代器 iter(range(10_000_000))~48 字节连计算都省了

差距是 6 位数级别的。

五、实战:什么时候该用生成器

适合用生成器的场景

场景原因
读取大文件(GB 级)不用一次性读入内存
数据管道/流处理上游产一个,下游消一个
无限序列列表存不下,生成器可以无限产生
中间结果不需要保留用完就丢,没必要存

示例:逐行读取大文件

python
# ❌ 错误:一次性读入内存
with open('huge_log.txt') as f:
    lines = f.readlines()  # 内存爆炸

# ✅ 正确:生成器逐行读取
with open('huge_log.txt') as f:
    for line in f:         # f 本身就是迭代器
        if 'ERROR' in line:
            print(line)

open() 返回的文件对象本身就是迭代器,每次 for 循环只读一行。

示例:数据管道

python
def read_log(filename):
    with open(filename) as f:
        for line in f:
            yield line.strip()

def filter_errors(lines):
    for line in lines:
        if 'ERROR' in line:
            yield line

def extract_time(lines):
    for line in lines:
        yield line.split()[0]

# 管道组合:数据从左到右流动,全程不存中间结果
pipeline = extract_time(filter_errors(read_log('app.log')))
for t in pipeline:
    print(t)

三个生成器串联,内存占用始终只有一行数据的大小

六、yield from:生成器嵌套的简洁写法

python
def gen1():
    yield 1
    yield 2

def gen2():
    yield from gen1()  # 等价于逐个 yield gen1() 的值
    yield 3

print(list(gen2()))  # [1, 2, 3]

yield from 还能透明传递 send()throw(),是生成器组合的推荐写法。

七、常见误区

误区真相
生成器比列表快不一定。生成器省内存,但有 yield 开销。小数据用列表更快
生成器可以倒回去不能。要重遍历,重新调用函数
yield 后的代码不执行执行,只是暂停。下次 next()yield 下一行继续
生成器表达式可以重复用不能。用完就空了,要重新创建

八、一张表总结

概念本质内存复用性典型写法
列表一次性存储所有元素✅ 可重复[x for x in range(n)]
迭代器边用边取,记住位置极低❌ 一次性iter(list)
生成器yield 实现的迭代器极低❌ 一次性(x for x in range(n))
生成器函数包含 yield 的函数极低❌ 一次性def f(): yield x

核心结论

  • 内存紧张时,能用生成器就别用列表
  • for 循环天然支持迭代器,改起来成本很低。
  • 文件对象、range()map()filter() 本身都是迭代器,直接用就行,别包一层 list()

省下来的内存,就是你程序能处理的数据量上限。

总结

到此这篇关于Python迭代器与生成器精讲之大幅降低内存占用的文章就介绍到这了,更多相关Python迭代器与生成器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 教你用 Python 实现微信跳一跳(Mac+iOS版)

    教你用 Python 实现微信跳一跳(Mac+iOS版)

    这几天看网上好多微信跳一跳破解了,不过都是安卓的,无奈苹果不是开源也没办法。本文给大家分享用 Python 来玩微信跳一跳(Mac+iOS版),具体实现代码大家参考下本文
    2018-01-01
  • opencv+python实现均值滤波

    opencv+python实现均值滤波

    这篇文章主要为大家详细介绍了opencv+python实现均值滤波,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • 一文轻松掌握python语言命名规范规则

    一文轻松掌握python语言命名规范规则

    这篇文章主要介绍了一文轻松掌握python语言命名规范规则,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • python3实现在二叉树中找出和为某一值的所有路径(推荐)

    python3实现在二叉树中找出和为某一值的所有路径(推荐)

    这篇文章主要介绍了python3实现在二叉树中找出和为某一值的所有路径,本文通过一个实例demo给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • 使用Python实现Fuzz测试的四种方法实现与对比

    使用Python实现Fuzz测试的四种方法实现与对比

    这篇文章将用Python实现一个类似的、存在漏洞的程序,并展示如何使用Python进行Fuzz测试,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2025-09-09
  • Python中PyQt5/PySide2的按钮控件使用实例

    Python中PyQt5/PySide2的按钮控件使用实例

    这篇文章主要介绍了PyQt5/PySide2的按钮控件使用实例,代码简单易懂,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-08-08
  • Python中sub()的用法说明

    Python中sub()的用法说明

    这篇文章主要介绍了Python中sub()的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Python打包为exe详细教程

    Python打包为exe详细教程

    今天给大家介绍如何用Python打包exe,文中有非常详细的教程,对正在学习python的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • Python实现二叉树的常见遍历操作总结【7种方法】

    Python实现二叉树的常见遍历操作总结【7种方法】

    这篇文章主要介绍了Python实现二叉树的常见遍历操作,结合实例形式总结分析了二叉树的前序、中序、后序、层次遍历中的迭代与递归等7种操作方法,需要的朋友可以参考下
    2019-03-03
  • 教你30分钟使用Python制作自己的记事本

    教你30分钟使用Python制作自己的记事本

    这篇文章主要为大家详细介绍了30分钟如何使用Python制作自己的记事本,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2026-02-02

最新评论