Python tricks(7) -- new-style class的__slots__属性
__slots__是在python 2.2开始引入的一个新特性, 我们来看一下官方给出的解释.
This class variable can be assigned a string, iterable, or sequence of strings with variable names used by instances. If defined in a new-style class, __slots__ reserves space for the declared variables and prevents the automatic creation of __dict__ and__weakref__ for each instance.
为声明的字段保留空间, 不再为每个实例生成一个__dict__和__weakref__. [参考文献1]
python默认定义的class是可以动态添加属性的, 代码示例如下
In [1]: class Test(object):
...: pass
...: In [2]: a = Test() In [3]: a.a = 1 In [4]: a.a
Out[4]: 1
可以动态地为a添加一个属性, 在class中会默认创建一个特殊的对象__dict__, 负责保存class的所有属性和方法.
这个__slots__主要的一个作用是减少了对内存的消耗, 这个尤其在对象数量较多的时候非常管用, 可以查看[参考文献3], 使用__slots__未作任何其他优化, 节省了9G内存.
示例代码如下
import sys
from guppy import hpy class Person_(object):
__slots__ = ("name", "age", "gender") def __init__(self):
pass class Person(object):
def __init__(self):
pass if __name__ == "__main__":
persons = []
for i in xrange(100000):
p = Person()
p.name = "name_%d" % i
p.age = i
p.gender = "female"
persons.append(p) persons_ = []
for i in xrange(100000):
p = Person_()
p.name = "name_%d" % i
p.age = i
p.gender = "female"
persons_.append(p) print "size without slots: %d" % sum([sys.getsizeof(p) for p in persons])
print "size of the __dict__ without slots: %d" % sum([sys.getsizeof(p.__dict__) for p in persons])
print "size of the __weakref__ without slots: %d" % sum([sys.getsizeof(p.__weakref__) for p in persons])
print "size with slots: %d" % sum([sys.getsizeof(p) for p in persons_]) h = hpy()
print h.heap()
程序输出结果如下:
size without slots: 3200000
size of the __dict__ without slots: 14000000
size of the __weakref__ without slots: 800000
size with slots: 3600000
Partition of a set of 739737 objects. Total size = 32889732 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 100000 14 14000000 43 14000000 43 dict of __main__.Person
1 214673 29 7335252 22 21335252 65 str
2 100000 14 3600000 11 24935252 76 __main__.Person_
3 100000 14 3200000 10 28135252 86 __main__.Person
4 209137 28 2509644 8 30644896 93 int
5 181 0 831828 3 31476724 96 list
6 7627 1 339356 1 31816080 97 tuple
7 331 0 232004 1 32048084 97 dict (no owner)
8 1670 0 120240 0 32168324 98 types.CodeType
9 73 0 110060 0 32278384 98 dict of module
<95 more rows. Type e.g. '_.more' to view.>
获取内存大小的两种方法: 一种使用sys.getsizeof()方法, 一种可以采用第三方库guppy的hpy来查看, 上面的示例代码同时使用了这两种方式
Person是默认的new-style class, Person_是带有slots的new-style class. 为二者创建100000个对象, 来查看内存大小.
直接算Person_的大小总共为3.6M左右, Person的大小为3.2M. 我一直很奇怪这个为什么反而大了呢?
后来发现貌似__dict__的大小没有被算进去, Person.__dict__的总大小为14M, 这样Person的总大小为17.2M, 而Person_没有__dict__属性, 总大小为3.6M, 由此可以看出, slots可以节省非常多的内存.
__dict__一般的实现都是用空间换取时间, 所以本身的内存消耗非常大, 在对象数量越多的时候越明显.
大家如果在项目中发现python占用很大内存的时候, 可以考虑从这个角度去进行内存优化, 大部分情况是可以取得不错的效果.
水平有限, 欢迎拍砖!
参考文献
- 官方文档: http://docs.python.org/2.7/reference/datamodel.html?highlight=slots#__slots__
- slots的源码分析: http://www.kvmapp.com/program/python/python-slots.html
- 节省内存的实例: http://tech.oyster.com/save-ram-with-python-slots/
Python tricks(7) -- new-style class的__slots__属性的更多相关文章
- Python属性、方法和类管理系列之----__slots__属性
一句话说明 __slots__是用来限制实例的属性的,__slots__可以规定实例是否应该有__dict__属性:__slots__不能限制类的属性. 只有__slots__列表内的这些变量名可赋值 ...
- 转载:Python中的new style class机制实现
1.Python中的对象模型python中所有东西都是对象 class对象:表示Python内置的类型和定义的类型instance对象(实例对象):表示由class对象创建的实例 1.1 对象间的关系 ...
- 类的__slots__属性
为什么有"slots"属性? 默认情况下,python对象队象的每个实例(instance)都会有一个字典来存储该实例的属性,这样做的好处在于运行时期每个对象可以任意设置新的属性. ...
- python进阶之类常用魔法方法和魔法属性
前言 前面我们总结过了python的关键字.运算符.内置函数.语法糖等与python魔法方法之间的关系,现在我们更细一点,看看python的面向对象编程有哪些常用的魔法属性和魔法方法. 魔法属性 对于 ...
- JS学习之DOM节点的关系属性封装、克隆节点、Dom中Style常用的一些属性等小结
JS DOM节点: 在JS DOM中节点的关系被定义为节点的属性: 通常有以下几种节点之间的关系: (这里的关系是所有浏览器都支持的) parentNode 父节点 childNodes ...
- 【python学习笔记】9.魔法方法、属性和迭代器
[python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...
- 二十六. Python基础(26)--类的内置特殊属性和方法
二十六. Python基础(26)--类的内置特殊属性和方法 ● 知识框架 ● 类的内置方法/魔法方法案例1: 单例设计模式 # 类的魔法方法 # 案例1: 单例设计模式 class Teacher: ...
- python 46 css组合选择器 及优先级 、属性选择器
一:css组合选择器 特性:每个选择器位可以为任意基本选择器或选择器组合 选择器分为以下几类: 群组选择器,子代(后代)选择器,相邻(兄弟)选择器,交集选择器,多类名选择器 1.群组选择器: d ...
- PyQt(Python+Qt)学习随笔:QAbstractItemView的textElideMode属性
老猿Python博文目录 老猿Python博客地址 一.概述 textElideMode属性用于控制省略文本中省略号"-"的位置,当项的内容过多视图无法显示完整时会显示部分内容,并 ...
- PyQt(Python+Qt)学习随笔:QAbstractItemView的defaultDropAction属性
老猿Python博文目录 老猿Python博客地址# 一.概述 defaultDropAction属性用于控制QAbstractItemView及其子类的实例视图中拖放时放下的默认操作.该属性的类型为 ...
随机推荐
- Core Data 迁移与版本管理
原文 http://chun.tips/blog/2014/11/28/core-data-ban-ben-qian-yi-jing-yan-zong-jie/ 主题 Core DataiOS开发 ...
- python nose测试框架全面介绍七--日志相关
引: 之前使用nose框架时,一直使用--logging-config的log文件来生成日志,具体的log配置可见之前python nose测试框架全面介绍四. 但使用一段时间后,发出一个问题,生成的 ...
- Unity3D笔记 英保通七 物理引擎
给球体添加刚体RigidBody和球体碰撞器Sphere Collider 效果: OnTriggerEnter() 代码 using UnityEngine; using System.Collec ...
- STM32下多串口用法
一个项目用到32下的多个串口,一般STM32C8T6型号拥有3个USART,串口的配置都很简单,但是要使用的话就得解决他们之间的矛盾, printf函数到底输出在哪一个串口中? 先看这函数: //重定 ...
- 通过JS模拟select表单,达到美化效果[demo][转]
转自: http://www.cnblogs.com/dreamback/p/SelectorJS.html 通过JS模拟select表单,达到美化效果 Demo ------------------ ...
- Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(转)
通过前面的学习,你可能大致了解了Quartz,本篇博文为你打开学习SSMM+Quartz的旅程!欢迎上车,开始美好的旅程! 本篇是在SSM框架基础上进行的. 参考文章: 1.Quartz学习——Qua ...
- Java-06-动手动脑
1.为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来? 因为子类继承于父类,子类中有父类的对象,父类的构造方法初始化后,子类才能运行自己的构造方法 不能放过来,继 ...
- 使用IntelliJ IDEA进行Python远程调试的需求(未完)
使用IntelliJ IDEA进行Python远程调试的需求(未完) 在研究深度学习Machlearning时,有时候需要借助ubuntu搭建的tensorflow环境,另外也有越来越多的运算程序只能 ...
- Git:上传GitHub项目操作步骤
git教程:git详解.gitbook #首次上传步骤 首先在工程文件位置处右键git bash here 本地创建ssh key $ ssh-keygen -t rsa -C "your_ ...
- Can you answer these queries?---hdu4027
题目链接 有n个数:当操作为1时求L到R的和: 当操作为0时更新L到R为原来的平方根: 不过如果仔细演算的话会发现一个2^64数的平方根开8次也就变成了 1,所以也更新不了多少次,所以可以每次更新到底 ...