Python 大量对象创建的内存优化方法
技术百科
冷漠man
发布时间:2026-01-27
浏览: 次 用 __slots__ 可将实例内存压缩至原来的1/3~1/5,因禁用__dict__和__weakref__,属性转为固定偏移存储;需显式声明属性名,父类启用则子类也须定义,否则优化失效。
用 __slots__ 禁用动态属性能省多少内存?
默认情况下,Python 每个实例都带一个 __dict__ 字典来存属性,哪怕只存 2

加 __slots__ 后,实例不再有 __dict__ 和 __weakref__,属性直接映射到预分配的固定偏移量,内存可压缩到原来的 1/3~1/5。
- 必须显式声明所有允许的属性名:
__slots__ = ('id', 'name', 'score') - 不能动态赋值未声明的属性,否则报
AttributeError: 'X' object has no attribute 'xxx' - 父类用了
__slots__,子类也得定义,否则父类的优化会被子类的__dict__覆盖 - 如果需要偶尔支持动态属性,可保留
'__dict__'在 slots 元组里,但那就失去大部分优化效果
对象池(__new__ + 缓存)适合哪些场景?
不是所有对象都适合池化。只有满足「创建开销大 + 生命周期短 + 实例可复用」三个条件时才值得做,比如网络连接、线程本地配置、坐标点(若业务中大量重复构造相同值)。
常见误用是拿它优化普通数据容器(如 User),反而因哈希/查找引入额外开销,且容易引发状态残留 bug。
- 用弱引用字典
weakref.WeakValueDictionary存缓存,避免对象永久驻留 - 重写
__new__时,先查池、命中则跳过super().__new__,未命中再创建并存入池 - 注意:池化后对象状态必须重置(例如在
__init__或复用前清空字段),否则上次使用残留的数据会污染下次调用 - 并发环境下需加锁(如
threading.Lock),但锁本身可能成为瓶颈,建议按 key 分片加锁
array.array 和 struct.pack 替代对象列表真能提速?
当你要存的是同构数值数据(比如十万条 (x: float, y: float, z: float)),用对象列表是典型的空间浪费:每个 Point 实例至少 48 字节 + 3 × 24 字节浮点对象引用 + 冗余类型信息。
换成 array.array('d', [...]) 或 struct.pack('ddd', x, y, z) 打包成二进制块,内存直接降到 1/5 以内,且 CPU 缓存友好,遍历速度通常快 3–10 倍。
-
array.array只支持基础类型('i','d','B'等),不支持嵌套或混合类型 - 用
struct需自己管理偏移和解包逻辑,适合固定结构+批量读写;array更适合单值追加和随机访问 - 如果后续要频繁按字段过滤(如 “找出所有 y > 10 的点”),纯 array 会逼你写 C 风格循环,此时可考虑
numpy.ndarray—— 它底层也是紧凑内存布局,还带向量化操作
为什么 __del__ 和弱回调不适合内存敏感场景?
很多人想靠 __del__ 主动归还资源或清理缓存,但这不可靠:CPython 中它依赖引用计数归零触发,PyPy/其他实现甚至不保证调用时机;循环引用下更可能永不触发。
弱引用回调(weakref.ref(obj, callback))看似优雅,但 callback 执行时机不确定,且每次注册都会产生额外对象(弱引用本身也有开销),在高频创建/销毁场景下反而增加 GC 压力。
- 真正可控的方式是显式生命周期管理:用上下文管理器(
with)、手动.close()、或把对象生命周期绑定到某个明确的 owner 上 - 如果必须自动清理,优先用
weakref.finalize(比__del__更可靠),但仍要避免在 finalize 里做耗时或依赖其他对象的操作 - 最省心的做法其实是别让对象活太久——用生成器替代一次性列表,用迭代器替代全量加载,从源头减少存活对象数
内存优化不是堆技巧,而是对数据建模方式的重新审视。一个 __slots__ 能省几百 MB,但若本该用 array 存的数据硬套 class,再怎么调参也救不回来。
# 的是
# 你要
# 那就
# 也有
# python
# 也要
# 复用
# 循环
# 并发
# 对象
# 堆
# class
# 字节
# 子类
# 为什么
# 线程
# 回调
# bug
# Struct
# Object
# Attribute
# Float
# 加锁
# 父类
# 浮点
# Array
# numpy
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Python字符串处理进阶_切片方法解析【指导】
- Mac上的iMovie如何剪辑视频?(新手入门教程
- Win11蓝牙开关不见了怎么办_Win11蓝牙驱动
- Win11怎么设置屏保时间_调整Win11屏幕保护
- Windows蓝屏错误0x00000018怎么处理
- 如何在 ACF 中正确更新嵌套多层 Group 字
- c++输入输出流 c++ cin与cout格式化输
- PHP怎么接收URL中的锚点参数_获取#后面参数值
- php在Linux怎么部署_LNMP环境搭建PHP
- Windows10系统服务优化指南_Win10禁用
- php怎么下载安装后无法解析php文件_服务器配置
- Go语言中CookieJar的持久化机制解析:内存
- 如何提升Golang程序I/O性能_Golang
- Win10如何卸载Skype_Win10卸载Sky
- Win11怎么设置任务栏透明_Windows11使
- 微信里的php文件怎么变mp4_微信接收php转m
- Go 语言标准库为何不提供泛型 Contains
- Go 中 defer 语句在 goroutine
- php报错怎么查看_定位PHP致命错误与警告的方法
- 如何在Golang中定义接口_抽象方法和多态实现
- 如何在Golang中使用time处理时间_Gola
- 如何使用Golang配置安全开发环境_防止敏感信息
- C++友元类使用场景_C++类间协作设计方式讲解
- php怎么捕获异常_trycatch结构处理运行时
- PythonFastAPI项目实战教程_API接口
- Win10如何更改网络连接_Windows10以太
- MAC怎么在照片中添加水印_MAC自带编辑工具文字
- Win11怎么设置虚拟内存_Windows 11优
- Windows如何使用注册表查找和删除项?(reg
- VSC怎么快速定位PHP错误行_错误追踪设置法【方
- Win11键盘快捷键大全_Windows 11常用
- Win11怎么关闭内容自适应亮度_Windows1
- Win11怎么设置虚拟桌面 Win11新建多桌面切
- XAMPP 启动失败(Apache 突然停止)的终
- 当网站SEO排名下降时,如何应对?
- Windows10系统怎么查看显卡驱动_Win10
- Win11怎么设置屏保_Windows 11屏幕保
- Windows怎样关闭Edge新标签页广告_Win
- MAC怎么解压RAR格式文件_MAC第三方解压工具
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- Win11怎么查看电脑配置_Win11硬件配置详细
- Win11怎么打开注册表_Windows 11注册
- php本地部署后session无法保存_sessi
- 如何使用 Selenium 正确获取篮球参考网站球
- c++ unordered_map怎么用 c++哈
- Windows蓝屏错误0x0000002C怎么解决
- MAC怎么设置程序窗口永远最前_MAC窗口置顶插件
- LINUX下如何配置VLAN虚拟局域网_在LINU
- php485读数据时阻塞怎么办_php485非阻塞
- 如何在 Django 中安全修改用户密码而不使会话

QQ客服