__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占用很大内存的时候, 可以考虑从这个角度去进行内存优化, 大部分情况是可以取得不错的效果.

水平有限, 欢迎拍砖!

参考文献

  1. 官方文档: http://docs.python.org/2.7/reference/datamodel.html?highlight=slots#__slots__
  2. slots的源码分析: http://www.kvmapp.com/program/python/python-slots.html
  3. 节省内存的实例: http://tech.oyster.com/save-ram-with-python-slots/

Python tricks(7) -- new-style class的__slots__属性的更多相关文章

  1. Python属性、方法和类管理系列之----__slots__属性

    一句话说明 __slots__是用来限制实例的属性的,__slots__可以规定实例是否应该有__dict__属性:__slots__不能限制类的属性. 只有__slots__列表内的这些变量名可赋值 ...

  2. 转载:Python中的new style class机制实现

    1.Python中的对象模型python中所有东西都是对象 class对象:表示Python内置的类型和定义的类型instance对象(实例对象):表示由class对象创建的实例 1.1 对象间的关系 ...

  3. 类的__slots__属性

    为什么有"slots"属性? 默认情况下,python对象队象的每个实例(instance)都会有一个字典来存储该实例的属性,这样做的好处在于运行时期每个对象可以任意设置新的属性. ...

  4. python进阶之类常用魔法方法和魔法属性

    前言 前面我们总结过了python的关键字.运算符.内置函数.语法糖等与python魔法方法之间的关系,现在我们更细一点,看看python的面向对象编程有哪些常用的魔法属性和魔法方法. 魔法属性 对于 ...

  5. JS学习之DOM节点的关系属性封装、克隆节点、Dom中Style常用的一些属性等小结

    JS DOM节点: 在JS DOM中节点的关系被定义为节点的属性: 通常有以下几种节点之间的关系: (这里的关系是所有浏览器都支持的) parentNode    父节点 childNodes     ...

  6. 【python学习笔记】9.魔法方法、属性和迭代器

    [python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...

  7. 二十六. Python基础(26)--类的内置特殊属性和方法

    二十六. Python基础(26)--类的内置特殊属性和方法 ● 知识框架 ● 类的内置方法/魔法方法案例1: 单例设计模式 # 类的魔法方法 # 案例1: 单例设计模式 class Teacher: ...

  8. python 46 css组合选择器 及优先级 、属性选择器

    一:css组合选择器 特性:每个选择器位可以为任意基本选择器或选择器组合 选择器分为以下几类: 群组选择器,子代(后代)选择器,相邻(兄弟)选择器,交集选择器,多类名选择器 1.群组选择器:    d ...

  9. PyQt(Python+Qt)学习随笔:QAbstractItemView的textElideMode属性

    老猿Python博文目录 老猿Python博客地址 一.概述 textElideMode属性用于控制省略文本中省略号"-"的位置,当项的内容过多视图无法显示完整时会显示部分内容,并 ...

  10. PyQt(Python+Qt)学习随笔:QAbstractItemView的defaultDropAction属性

    老猿Python博文目录 老猿Python博客地址# 一.概述 defaultDropAction属性用于控制QAbstractItemView及其子类的实例视图中拖放时放下的默认操作.该属性的类型为 ...

随机推荐

  1. 阿里云安装Oracle

    #!/bin/bash #writed by kangjie -- ######################################### #如果没有交换分区swap,则创建 # #检查 ...

  2. vue之单表输入绑定

    vue的核心:声明式的指令和数据的双向绑定. 那么声明式的指令,已经给大家介绍完了.接下来我们来研究一下什么是数据的双向绑定? 另外,大家一定要知道vue的设计模式:MVVM M是Model的简写,V ...

  3. Python面向对象之字段

    类成员: 字段,方法,属性 属性是在一个函数方法前面加一个装饰器,伪造成为一个字段,调用的时候不需要加括号() 目的是把一个方法伪造成为一个字段,属性也是方法的一种,对这个方法进行改造就可以以 字段的 ...

  4. CentOS6.5安装配置PPTP

    本次安装环境为Ucloud云服务器 1,操作系统版本检查 2,安装ppp,pptp yum install -y ppp rpm -ivh http://static.ucloud.cn/pptpd- ...

  5. HOJ 1438 The Tower of Babylon(线性DP)

    The Tower of Babylon My Tags Cancel - Seperate tags with commas. Source : University of Ulm Internal ...

  6. poj3261 Milk Patterns【后缀数组】【二分】

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On furthe ...

  7. 2018-2019-2 20165330《网络对抗技术》Exp1 PC平台逆向破解

    目录 实验目标 实验内容 知识点描述 实验步骤 实验过程中遇到的问题 实验感想 实验目标 本次实验的对象是一个名为pwn1的linux可执行文件. -该程序正常执行流程是:main调用foo函数,fo ...

  8. codeforces 592B/C

    题目链接:http://codeforces.com/contest/592/problem/B B. The Monster and the Squirrel time limit per test ...

  9. HDU 2819 - Swap - [二分图建模+最大匹配]

    题目链接:https://cn.vjudge.net/problem/HDU-2819 Given an N*N matrix with each entry equal to 0 or 1. You ...

  10. Blocks POJ - 1390 多维dp

    题意:有一排box,各有不同的颜色.你可以通过点击某个box使得与其相邻的同色box全部消掉,然后你可以得到的分数为消去长度的平方,问怎样得到最高分? 题解:考虑用一维dp,/*dp[i]为1~i个b ...