当前位置:首页>python>Python 列表推导式一步写错,内存直接爆炸 100 倍!

Python 列表推导式一步写错,内存直接爆炸 100 倍!

  • 2026-10-25 20:14:25
Python 列表推导式一步写错,内存直接爆炸 100 倍!

你以为列表推导式很简单?

一行代码写错,内存直接从 80MB 飙到 8GB!

今天分享一个真实踩坑经历,看完你就知道为什么了。

▶ 先看问题代码

同事写了一段处理数据的代码,跑着跑着服务器就 OOM 了。

```python# ❌ 错误写法:内存爆炸data = [x * 2 for x in range(100000000)]  # 1亿条数据```

这行代码看起来没问题,但它会立即在内存中创建 1 亿个元素的列表

我用 memory_profiler 测了一下:

```pythonfrom memory_profiler import profile@profiledefbad_example():    data = [x * 2for x inrange(100000000)]    returnsum(data)bad_example()```

结果:内存占用 8GB!

▶ 正确写法:生成器表达式

只需要把方括号 `[]` 换成圆括号 `()`:

```python# ✅ 正确写法:内存友好data = (x * 2for x inrange(100000000))  # 生成器```

同样的测试:

```python@profiledefgood_example():    data = (x * 2for x inrange(100000000))    returnsum(data)good_example()```

结果:内存占用只有 80MB!

差了 100 倍!

▶ 为什么差这么多?

列表推导式 `[]`:

  • 立即执行,一次性生成所有元素

  • 所有数据都存在内存里

  • 数据量大时,内存直接爆炸

生成器表达式 `()`:

  • 惰性求值,用到才计算

  • 每次只生成一个元素

  • 内存占用恒定,不随数据量增长

```python# 列表:立即生成全部[x for x inrange(1000000)]  # 内存中有100万个元素# 生成器:按需生成(x for x inrange(1000000))  # 内存中只有1个元素```

▶ 什么时候用哪个?

记住这个原则:

数据量大 + 只遍历一次 = 用生成器!

▶ 实战对比

处理一个 1000 万行的日志文件:

```python# ❌ 错误:一次性读入内存lines = [line.strip() for line inopen('huge.log')]result = [line for line in lines if'ERROR'in line]# ✅ 正确:流式处理lines = (line.strip() for line inopen('huge.log'))result = (line for line in lines if'ERROR'in line)# 只在需要时才真正读取for error_line in result:    print(error_line)```

效果:

  • 错误写法:内存占用 2GB+

  • 正确写法:内存占用 < 10MB

▶ 更多省内存技巧

1、用 itertools 处理大数据

```pythonimport itertools# 取前100个first_100 = itertools.islice(huge_generator, 100)# 链接多个生成器combined = itertools.chain(gen1, gen2, gen3)```

2、用 yield 写生成器函数

```pythondefread_large_file(file_path):    withopen(file_path) as f:        for line in f:            yield line.strip()# 使用for line in read_large_file('huge.log'):    process(line)```

3、pandas 分块读取

```pythonimport pandas as pd# ❌ 一次性读取df = pd.read_csv('huge.csv')  # 内存爆炸# ✅ 分块读取for chunk in pd.read_csv('huge.csv', chunksize=10000):    process(chunk)```

▶ 常见误区

**误区 1:生成器更慢?**

不一定!生成器省去了内存分配的开销,有时反而更快。

**误区 2:生成器可以重复使用?**

不行!生成器只能遍历一次,遍历完就空了。

```pythongen = (x for x inrange(5))print(list(gen))  # [0, 1, 2, 3, 4]print(list(gen))  # []  空了!```

**误区 3:所有地方都用生成器?**

不对!数据量小的时候,列表更方便,可以索引、切片、多次遍历。

【总结】

一句话总结:

数据量大就用 `()`,数据量小就用 `[]`,别搞混了!

#程序员 #开发 #代码 #Python #内存优化

最新文章

随机文章