Python中的__slots__示例详解


Posted in Python onJuly 06, 2017

前言

相信Python老鸟都应该看过那篇非常有吸引力的Saving 9 GB of RAM with Python's slots 文章,作者使用了__slots__让内存占用从25.5GB降到了16.2GB。在当时来说,这相当于用一个非常简单的方式就降低了30%的内存使用,着实惊人。作者并没有提到他的业务特点和代码,那我们就基于《fluent python》中的例子来验证下是不是有这么厉害:

from __future__ import print_function
import resource
class A(object):
 def __init__(self):
 self.a = 'string'
 self.b = 10
 self.c = True
class B(object):
 __slots__ = ['a', 'b', 'c']
 def __init__(self):
 self.a = 'string'
 self.b = 10
 self.c = True
def test(cls):
 mem_init = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
 l = []
 for i in range(500000):
 l.append(cls())
 mem_final = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
 del l
 print('Class: {}:\n'.format(getattr(cls, '__name__')))
 print('Initial RAM usage: {:14,}'.format(mem_init))
 print(' Final RAM usage: {:14,}'.format(mem_final))
 print('-' * 20)
if __name__ == '__main__':
 import sys
 test(globals()[sys.argv[1].upper()])

我们分别跑一下这2个类:

❯ python mem_test.py a
Class: A:
Initial RAM usage: 4,890,624
 Final RAM usage: 200,454,144
--------------------
❯ python mem_test.py b
Class: B:
Initial RAM usage: 4,919,296
 Final RAM usage: 60,235,776

2种方法初始内存略有差别,但是由于这个差别和总内存量相比太小而忽略不计,结论就是:

使用slots可以让内存使用减少3.5倍!!# 通过 (200 - 4) / ((60 - 4) * 1.0) 计算得来

那么用slot就是非非常那个有必要吗?事实上500000个实例这种机会非常少见,用不用完全根据业务来决定,并不要以偏概全。因为(敲黑板了哈)使用__slots__也是有副作用的:

  1. 每个继承的子类都要重新定义一遍__slots__
  2. 实例只能包含哪些在__slots__定义的属性,这对写程序的灵活性有影响,比如你由于某个原因新网给instance设置一个新的属性,比如instance.a = 1, 但是由于a不在__slots__里面就直接报错了,你得不断地去修改__slots__或者用其他方法迂回的解决
  3. 实例不能有弱引用(weakref)目标,否则要记得把__weakref__放进__slots__

第三点有点难理解,我写个例子看看吧:

In [2]: %pycat ref_example.py
from weakref import ref
class A(object):
 __slots__ = ['b']
 def __init__(self):
 self.b = 1
class B(object):
 __slots__ = ['b', '__weakref__']
 def __init__(self):
 self.b = 1
In [3]: from ref_example import *
In [4]: a = A()
In [5]: r = ref(a)
---------------------------------------------------------------------------
TypeError     Traceback (most recent call last)
<ipython-input-6-75a6d689c8b3> in <module>()
----> 1 r = ref(a)
TypeError: cannot create weak reference to 'A' object
In [6]: b = B()
In [7]: r = ref(b)
In [8]: r
Out[8]: <weakref at 0x109199578; to 'B' at 0x10919f890>

所以实例不超过万级别的类,__slots__是不太值得使用的。

PS: 《fluent python》比我狠,说的是小于百万级别实例不值得使用。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python打开网页和暂停实例
Sep 30 Python
Python上下文管理器和with块详解
Sep 09 Python
Django的分页器实例(paginator)
Dec 01 Python
python验证码识别教程之利用滴水算法分割图片
Jun 05 Python
TensorFlow用expand_dim()来增加维度的方法
Jul 26 Python
查看Python依赖包及其版本号信息的方法
Aug 13 Python
python实现的读取网页并分词功能示例
Oct 29 Python
python如何实现不可变字典inmutabledict
Jan 08 Python
python实现扑克牌交互式界面发牌程序
Apr 22 Python
浅谈numpy中函数resize与reshape,ravel与flatten的区别
Jun 18 Python
python munch库的使用解析
May 25 Python
python opencv将多个图放在一个窗口的实例详解
Feb 28 Python
利用python获取Ping结果示例代码
Jul 06 #Python
Python中工作日类库Busines Holiday的介绍与使用
Jul 06 #Python
Python中动态检测编码chardet的使用教程
Jul 06 #Python
Python解析json之ValueError: Expecting property name enclosed in double quotes: line 1 column 2(char 1)
Jul 06 #Python
CentOS 7下Python 2.7升级至Python3.6.1的实战教程
Jul 06 #Python
Python中定时任务框架APScheduler的快速入门指南
Jul 06 #Python
Python如何快速实现分布式任务
Jul 06 #Python
You might like
php面向对象全攻略 (七) 继承性
2009/09/30 PHP
php上的memcache和memcached两个pecl库
2010/03/29 PHP
微信支付开发告警通知实例
2016/07/12 PHP
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
2009/11/12 Javascript
基于jquery的tab切换 js原理
2010/04/01 Javascript
改变隐藏的input中value的值代码
2013/12/30 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
使用jQuery实现星级评分代码分享
2014/12/09 Javascript
jQuery中parent()方法用法实例
2015/01/07 Javascript
js+html5绘制图片到canvas的方法
2015/06/05 Javascript
javascript图片预加载实例分析
2015/07/16 Javascript
jquery实现的Banner广告收缩效果代码
2015/09/02 Javascript
JS实现完全语义化的网页选项卡效果代码
2015/09/15 Javascript
详解JavaScript中的构造器Constructor模式
2016/01/14 Javascript
jQuery中通过ajax的get()函数读取页面的方法
2016/02/29 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
Bootstrap选项卡学习笔记分享
2017/02/13 Javascript
详解react-webpack2-热模块替换[HMR]
2017/08/03 Javascript
详解vue-cli构建项目反向代理配置
2017/09/07 Javascript
JavaScript去掉数组重复项的方法分析【测试可用】
2018/07/19 Javascript
vue中实现动态生成二维码的方法
2020/02/21 Javascript
vue实现五子棋游戏
2020/05/28 Javascript
JavaScript实现页面高亮操作提示和蒙板
2021/01/04 Javascript
Python3.5实现的三级菜单功能示例
2019/03/25 Python
Django框架中间件(Middleware)用法实例分析
2019/05/24 Python
python Django编写接口并用Jmeter测试的方法
2019/07/31 Python
python+Django实现防止SQL注入的办法
2019/10/31 Python
Django-migrate报错问题解决方案
2020/04/21 Python
python中怎么表示空值
2020/06/19 Python
你需要学会的8个Python列表技巧
2020/06/24 Python
python 贪心算法的实现
2020/09/18 Python
聚美优品陈欧广告词
2014/03/14 职场文书
研究生求职自荐书
2014/06/23 职场文书
毕业典礼主持词
2015/06/29 职场文书
2016年推广普通话宣传周活动总结
2016/04/06 职场文书
使用 Apache Dubbo 实现远程通信(微服务架构)
2022/02/12 Servers