Python内存管理技巧,一篇文章告诉你内存优化的本质!

大家好!💡还记得你第一次写 Python 代码的时候吗?那种随意创建变量、毫无节制地 new 一个又一个对象的快感,简直让人沉迷! 可是,当代码运行变慢、内存占用飙升时,你才会意识到:

 

“诶?怎么 Python 还会吃这么多内存?!”

今天,我们就来聊聊 Python 的内存管理,帮你写出更高效、优化内存占用的 Python 代码!🎯


包含编程资料、学习路线图、源代码、软件安装包等!【点击这里免费领取】 


1. Python 的内存管理机制

Python 内部使用 引用计数(Reference Counting) 和 垃圾回收(Garbage Collection, GC) 机制来管理内存。

1.1 引用计数

每个对象都有一个“计数器”,记录它被多少个变量引用。一旦引用计数归零,Python 立刻释放这个对象的内存。

import sys

a = []  # 创建一个列表对象
print(sys.getrefcount(a))  # 输出 2(因为 sys.getrefcount() 也会额外增加一次引用)

b = a  # 变量 b 也指向同一个列表
print(sys.getrefcount(a))  # 输出 3

del a
print(sys.getrefcount(b))  # 输出 2

del b  # 引用计数归零,内存被释放

💡 注意sys.getrefcount() 的结果比你想象的多 1,因为它本身也会创建一个临时引用!

1.2 垃圾回收(GC)

Python 采用 分代回收,对象被分成三代:新生代、中生代、老生代。垃圾回收主要针对循环引用的情况。

import gc

class A:
    def __init__(self):
        self.ref = None

obj1 = A()
obj2 = A()
obj1.ref = obj2
obj2.ref = obj1  # 形成循环引用

del obj1, obj2  # 引用计数没有归零,Python 需要 GC 来清理

gc.collect()  # 手动触发垃圾回收

2. Python 内存优化技巧

2.1 使用 __slots__限制对象属性

默认情况下,Python 的对象使用 动态字典(__dict__ 存储属性,占用大量内存。如果你的类属性是固定的,可以用 __slots__ 优化,之前花姐在其它文章中提到过。

class NormalClass:
    pass

class SlotClass:
    __slots__ = ['name', 'age']  # 仅允许 name 和 age 两个属性

obj1 = NormalClass()
obj1.name = "花姐"
obj1.age = 18
obj1.gender = "女"  # 允许动态添加新属性

obj2 = SlotClass()
obj2.name = "花姐"
obj2.age = 18
# obj2.gender = "女"  # ❌ AttributeError: 'SlotClass' object has no attribute 'gender'

__slots__ 会让 Python 不再为对象创建 __dict__,从而减少内存占用。

2.2 避免不必要的临时变量

Python 解释器会缓存一些常见的对象,例如 小整数-5 到 256 在 Python 3.9 及以前的版本),以及部分 短字符串

但在 Python 3.10+ 之后,整数的缓存范围 可能更大,具体行为依赖于 Python 实现。

# 可能被缓存(具体范围取决于 Python 版本)
a = 256
b = 256
print(a is b)  # True

# 可能不被缓存
a = 257
b = 257
print(a is b)  # 3.9 以前通常 False,3.10+ 可能 True

结论:Python 会缓存小整数,但具体范围视 Python 版本而定,不建议过分依赖此特性!

2.3 使用生成器代替列表

如果你只需要 逐个获取数据,而不是一次性加载所有数据,请用 生成器 代替列表。

# 占用大量内存的方式
nums = [i for i in range(10**6)]

# 更优的方式(惰性加载)
def num_generator():
    for i in range(10**6):
        yield i

gen = num_generator()

为什么? 生成器不会一次性把所有数据存入内存,而是每次 yield 一个值,这样可以大幅降低内存占用!🎉

2.4 使用 array 代替列表存储大量数值

如果你需要存储大量的数值,使用 array 模块比 list 更节省内存。

import array

# 创建一个存储 int 类型的数组,比列表更节省内存
arr = array.array('i', range(10**6))

2.5 使用 deque 代替列表进行队列操作

collections.deque 具有更高效的 头部插入和删除 操作,比 list 的 pop(0) 和 insert(0, x) 更优。

from collections import deque

dq = deque(range(10**6))
dq.appendleft(-1)  # O(1) 复杂度

# 而 list.insert(0, -1) 是 O(n),在大规模数据下性能差距明显

3. 释放不用的内存

3.1 手动释放变量

Python 采用 自动垃圾回收,但如果你想主动释放大对象,建议使用 del 并 调用 gc.collect()

import gc

data = [i for i in range(10**6)]
del data  # 删除变量
gc.collect()  # 强制触发垃圾回收

在大数据处理中,这个方法可以 显著减少内存占用


总结

  1. Python 采用 引用计数 + 垃圾回收 来管理内存。

  2. 使用 __slots__ 可以节省对象的 属性存储空间

  3. 避免不必要的临时变量,Python 会缓存小整数,但范围 依赖 Python 版本

  4. 用生成器替代列表,节省内存!

  5. 用 array 代替 list 存储大量数值,提高内存效率。

  6. 用 deque 代替 list 进行队列操作,提高性能。

  7. 手动释放大对象,使用 del + gc.collect() 及时清理。

希望今天的内容对你有帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值