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

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

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

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

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

▶ 先看问题代码

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

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

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

我用 memory_profiler 测了一下:

```python
from memory_profiler import profile

@profile
def bad_example():
 data = [x * 2 for x in range(100000000)]
return sum(data)

bad_example()
```

结果:内存占用 8GB!

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

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

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

同样的测试:

```python
@profile
def good_example():
 data = (x * 2 for x in range(100000000))
return sum(data)

good_example()
```

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

差了 100 倍!

▶ 为什么差这么多?

列表推导式 `[]`:

  • 立即执行,一次性生成所有元素
  • 所有数据都存在内存里
  • 数据量大时,内存直接爆炸

生成器表达式 `()`:

  • 惰性求值,用到才计算
  • 每次只生成一个元素
  • 内存占用恒定,不随数据量增长
```python
# 列表:立即生成全部
[x for x in range(1000000)] # 内存中有100万个元素

# 生成器:按需生成
(x for x in range(1000000)) # 内存中只有1个元素
```

▶ 什么时候用哪个?

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

记住这个原则:

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

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

▶ 实战对比

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

```python
# ❌ 错误:一次性读入内存
lines = [line.strip() for line in open('huge.log')]
result = [line for line in lines if 'ERROR' in line]

# ✅ 正确:流式处理
lines = (line.strip() for line in open('huge.log'))
result = (line for line in lines if 'ERROR' in line)

# 只在需要时才真正读取
for error_line in result:
print(error_line)
```

效果:

  • 错误写法:内存占用 2GB+
  • 正确写法:内存占用 < 10MB

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

▶ 更多省内存技巧

1、用 itertools 处理大数据

```python
import itertools

# 取前100个
first_100 = itertools.islice(huge_generator, 100)

# 链接多个生成器
combined = itertools.chain(gen1, gen2, gen3)
```

2、用 yield 写生成器函数

```python
def read_large_file(file_path):
with open(file_path) as f:
for line in f:
yield line.strip()

# 使用
for line in read_large_file('huge.log'):
 process(line)
```

3、pandas 分块读取

```python
import pandas as pd

# ❌ 一次性读取
df = pd.read_csv('huge.csv') # 内存爆炸

# ✅ 分块读取
for chunk in pd.read_csv('huge.csv', chunksize=10000):
 process(chunk)
```

▶ 常见误区

误区 1:生成器更慢?

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

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

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

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

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

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

【总结】

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

一句话总结:

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

━━━━━━━━━━━━━━━━━━━━

觉得有用的话,点个赞收藏一下吧!
有问题可以在评论区留言,我会回复的~
关注我,持续分享 Python 实战技巧!

#程序员##开发##代码##Python#

© 版权声明

相关文章

暂无评论

none
暂无评论...