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

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() # 强制触发垃圾回收

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

总结

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

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

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

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

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

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

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

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

相关推荐

霸气的徐姓好名字
beat365平台正版

霸气的徐姓好名字

📅 07-01 👁️ 9884
微博评论如何发照片?
365bet线上网址

微博评论如何发照片?

📅 07-26 👁️ 6496
潮牌男装在哪里进货(我想开时尚潮流衣服店。但是进货渠道,不知道怎么选择?)
365bet娱乐网

潮牌男装在哪里进货(我想开时尚潮流衣服店。但是进货渠道,不知道怎么选择?)

📅 07-07 👁️ 1399