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系列之从文件读取和保存数据
May 23 Python
Python脚本实现DNSPod DNS动态解析域名
Feb 14 Python
基于进程内通讯的python聊天室实现方法
Jun 28 Python
python使用webdriver爬取微信公众号
Aug 31 Python
python 制作自定义包并安装到系统目录的方法
Oct 27 Python
在Pycharm中将pyinstaller加入External Tools的方法
Jan 16 Python
python 提取文件指定列的方法示例
Aug 07 Python
Python List列表对象内置方法实例详解
Oct 22 Python
如何在VSCode下使用Jupyter的教程详解
Jul 13 Python
Python实现图片查找轮廓、多边形拟合、最小外接矩形代码
Jul 14 Python
Python异常处理机制结构实例解析
Jul 23 Python
Python 合并拼接字符串的方法
Jul 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
jq的get传参数在utf-8中乱码问题的解决php版
2008/07/23 PHP
Linux下实现PHP多进程的方法分享
2012/08/16 PHP
用PHP来计算某个目录大小的方法
2014/04/01 PHP
修改destoon会员公司的伪静态中的com目录的方法
2014/08/21 PHP
php利用事务处理转账问题
2015/04/22 PHP
利用PHP如何写APP接口详解
2016/08/23 PHP
php 获取xml接口数据的处理方法
2018/05/31 PHP
利用PHP扩展Xhprof分析项目性能实践教程
2018/09/05 PHP
PHP的PDO大对象(LOBs)
2019/01/27 PHP
JQuery中对Select的option项的添加、删除、取值
2013/08/25 Javascript
javascript数组操作总结和属性、方法介绍
2014/04/05 Javascript
简单谈谈javascript Date类型
2015/09/06 Javascript
分享纯手写漂亮的表单验证
2015/11/19 Javascript
JS加载器如何动态加载外部js文件
2016/05/26 Javascript
JavaScript正则表达式实例详解
2016/10/16 Javascript
简单三步实现报表页面集成天气
2016/12/15 Javascript
JavaScript中的遍历详解(多种遍历)
2017/04/07 Javascript
利用webstrom调试Vue.js单页面程序的方法教程
2017/06/06 Javascript
Angularjs实现页面模板清除的方法
2018/07/20 Javascript
JavaScript引用类型Object常见用法实例分析
2018/08/08 Javascript
Vue绑定内联样式问题
2018/10/17 Javascript
如何检查一个对象是否为空
2019/04/11 Javascript
Fetch超时设置与终止请求详解
2019/05/18 Javascript
vue.js实现备忘录demo
2019/06/26 Javascript
VUE 自定义组件模板的方法详解
2019/08/30 Javascript
Paypal支付不完全指北
2020/06/04 Javascript
python中正则表达式的使用详解
2014/10/17 Python
python中zip和unzip数据的方法
2015/05/27 Python
对python 多线程中的守护线程与join的用法详解
2019/02/18 Python
基于K.image_data_format() == 'channels_first' 的理解
2020/06/29 Python
YesBabyOnline美国:全球性的在线婚纱礼服工厂
2018/05/05 全球购物
培训班开班仪式主持词
2014/03/28 职场文书
父亲节活动策划方案
2014/08/24 职场文书
2014年调度员工作总结
2014/11/19 职场文书
赢在中国观后感
2015/06/02 职场文书
基于Python和openCV实现图像的全景拼接详细步骤
2021/10/05 Python