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变量不能以数字打头详解
Jul 06 Python
Python使用re模块正则提取字符串中括号内的内容示例
Jun 01 Python
Python 实现异步调用函数的示例讲解
Oct 14 Python
python3正则提取字符串里的中文实例
Jan 31 Python
pycharm重命名文件的方法步骤
Jul 29 Python
关于Python形参打包与解包小技巧分享
Aug 24 Python
Python Django框架模板渲染功能示例
Nov 08 Python
关于Keras模型可视化教程及关键问题的解决
Jan 24 Python
Python单链表原理与实现方法详解
Feb 22 Python
tensorflow/core/platform/cpu_feature_guard.cc:140] Your CPU supports instructions that this T
Jun 22 Python
Python命名空间及作用域原理实例解析
Aug 12 Python
能让Python提速超40倍的神器Cython详解
Jun 24 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 变量未定义等错误的解决方法
2011/01/12 PHP
深入探讨:Nginx 502 Bad Gateway错误的解决方法
2013/06/03 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
2015/08/31 PHP
PHP截取IE浏览器并缩小原图的方法
2016/03/04 PHP
抛弃 PHP 代价太高
2016/04/26 PHP
thinkPHP实现递归循环栏目并按照树形结构无限极输出的方法
2016/05/19 PHP
PHP实现多级分类生成树的方法示例
2017/02/07 PHP
PHP实现模拟http请求的方法分析
2017/12/20 PHP
thinkphp框架类库扩展操作示例
2019/11/26 PHP
newxtree.js代码
2007/03/13 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
Js 去掉字符串中的空格(实现代码)
2013/11/19 Javascript
开发插件的两个方法jquery.fn.extend与jquery.extend
2013/11/21 Javascript
浅谈JavaScript函数参数的可修改性问题
2013/12/05 Javascript
PHP守护进程实例
2015/03/06 Javascript
JavaScript中数据结构与算法(四):串(BF)
2015/06/19 Javascript
jQuery实现Tab选项卡切换效果简单演示
2015/11/23 Javascript
AngularJS页面访问时出现页面闪烁问题的解决
2016/03/06 Javascript
JavaScript实现父子dom同时绑定两个点击事件,一个用捕获,一个用冒泡时执行顺序的方法
2017/03/30 Javascript
垃圾回收器的相关知识点总结
2018/05/13 Javascript
vue更改数组中的值实例代码详解
2020/02/07 Javascript
深入理解python中的浅拷贝和深拷贝
2016/05/30 Python
python生成随机图形验证码详解
2017/11/08 Python
学习python可以干什么
2019/02/26 Python
django-filter和普通查询的例子
2019/08/12 Python
基于Tensorflow批量数据的输入实现方式
2020/02/05 Python
CSS3制作轮播图的一种方法
2019/11/11 HTML / CSS
canvas进阶之如何画出平滑的曲线
2018/10/15 HTML / CSS
美国豪华的多品牌精品店:The Webster
2019/07/31 全球购物
什么是静态路由,其特点是什么?什么是动态路由,其特点是什么?
2013/07/26 面试题
初中学校军训方案
2014/05/09 职场文书
优秀少先队工作者事迹材料
2014/05/13 职场文书
朋友聚会开场白
2015/06/01 职场文书
生死牛玉儒观后感
2015/06/11 职场文书
MySQL 使用事件(Events)完成计划任务
2021/05/24 MySQL
vue-cli3.0修改打包后的文件名和文件地址,打包后本地运行报错解决
2022/04/06 Vue.js