类的__slots__属性
为什么有"slots"属性?
默认情况下,python对象队象的每个实例(instance)都会有一个字典来存储该实例的属性,这样做的好处在于运行时期每个对象可以任意设置新的属性。而相对应的坏处是,当创建成百上千个这样的实例的时候回很浪费内存。所以引入__slots__
,用来指定实例只拥有固定的属性,因此python会给每个实例对象分配固定的内存空间,从而减少内存消耗。而且使用__slots__
可以加快属性的访问。
用法
__slots__
可以被设置成属性名称的字符串,可遍历的对象或者序列。
之前在看odoo源码缓存相关的内容时,看到过下面这个例子:
class ormcache_counter(object):
""" Statistic counters for cache entries. """
__slots__ = ['hit', 'miss', 'err']
def __init__(self):
self.hit = 0
self.miss = 0
self.err = 0
@property
def ratio(self):
return 100.0 * self.hit / (self.hit + self.miss or 1)
这里创建了一个用来记录每个方法缓存情况的对象,因为对于需要每个缓存的方法,都会创建一个该实例来记录缓存的状况(比如缓存用到或没用的次数等),所以为了节省内存加快访问速度这里指定了该对象拥有的三个属性。
测试
访问速度测试
timeit是python一个用来简单测试运行时间的模块,详细可参见官方文档。
# In Python2.7
# test1.py
import timeit
class Foo(object): __slots__ = 'foo',
class Bar(object): pass
slotted = Foo()
not_slotted = Bar()
def get_set_delete_fn(obj):
def get_set_delete():
obj.foo = 'foo'
obj.foo
del obj.foo
return get_set_delete
# In REPL
>>> from test1 import *
>>> min(timeit.repeat(get_set_delete_fn(not_slotted)))
min(timeit.repeat(get_set_delete_fn(not_slotted)))
0.24305510520935059
>>> min(timeit.repeat(get_set_delete_fn(slotted)))
min(timeit.repeat(get_set_delete_fn(slotted)))
0.21287798881530762
可以看见,使用__slots__
的对象有更快的访问速度,虽然在python2.7中差别没有在python3中那么明显
内存占用参考
关于内存占用情况的测试我还没测,但可以参考 stackoverflow上的测试,我这里机(无)智(耻)地取个结果:
# 单位 bytes
attrs __slots__ no slots declared + __dict__
none 16 64 (+ 280 if __dict__ referenced)
one 56 64 + 280
two 64 64 + 280
six 96 64 + 1048
22 224 64 + 3352
可以明显看到内存占用减少的情况。
注意事项
__dict__
可以理解成类里面存储属性的字典,
- 当一个类A继承自一个没有定义
__slots__
的类B时,A是有__dict__
属性,这是再定义__slots__
属性没有意义, 不能达到限制内存的作用 - 当尝试给一个定义了
__slots__
的类,而没有定义__dict__
的类设置不在__slots__
指定的那些属性时,会导致一个AttributeError
其它注意请参照文档
类的__slots__属性的更多相关文章
- python类的__slots__属性、__del__属性、上下文(__enter__和__exit__)、
常规情况下,类的属性字典是共享的,而实例的字典是独立的.如果一个类的属性较少,但是拥有很多的实例,这些实例的属性字典会占用较多的内存空间.对这样的类来说,为了节省内存空间,可以使用__slots__类 ...
- Python属性、方法和类管理系列之----__slots__属性
一句话说明 __slots__是用来限制实例的属性的,__slots__可以规定实例是否应该有__dict__属性:__slots__不能限制类的属性. 只有__slots__列表内的这些变量名可赋值 ...
- Python 类的高级属性(可选)
1.slots实例:限制类的实例有合法的属性集,只有__slots__属性列表中的属性才可能成为实例属性. 对象的实例通常没有一个属性字典,可以在__slots__列表中包含一个属性字典__dict_ ...
- __slots__属性
使用__slots__时,子类不受影响 class Person(object): __slots__ = ("name","age") def __str__ ...
- Python的动态语言特性; __slots__属性
python是动态语言 1. 动态语言的定义 动态编程语言 是 高级程序设计语言 的一个类别,在计算机科学领域已被广泛应用.它是一类 在运行时可以改变其结构的语言 :例如新的函数.对象.甚至代码可以被 ...
- id选择器、类选择器、属性选择器
在网页编辑时,通常要对样式进行各种设置.我们借助CSS样式设计中的选择器,就能很好很方便的对它们进行管理和设置了. 今天,跟大家分享一下几个常用的选择器:id选择器.类选择器.属性选择器. id选择器 ...
- JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...
- 转载:java 中对类中的属性使用set/get方法的意义和用法
经常看到有朋友提到类似:对类中的属性使用set/get方法的作用?理论的回答当然是封闭性之类的,但是这样对我们有什么作用呢?为什么要这样设计?我直接使用属性名来访问不是更直接,代码更简洁明了吗?下面我 ...
- java基础—继承题目:编写一个Animal类,具有属性:种类;具有功能:吃、睡。定义其子类Fish
编写一个Animal类,具有属性:种类:具有功能:吃.睡.定义其子类Fish package zhongqiuzuoye; public class Animal { //属性 private Str ...
随机推荐
- Netbeans Platform 工程,免安装JDK
使用Netbeans 6.8 创建了一个Netbeans Platform 工程,以Zip形式发布后, 按照以下操作,可 以在客户端免安装JDK: 1. 从已安装JDK的计算机中,提取JDK:eg. ...
- mysql show processlist 命令详解
命令格式 SHOW [FULL] PROCESSLIST SHOW PROCESSLIST显示哪些线程正在运行.您也可以使用mysqladmin processlist语句得到此信息.如果您有SUPE ...
- HDU 5821 Ball (排序)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5821 有n个盒子,每个盒子最多装一个球. 现在进行m次操作,每次操作可以将l到r之间盒子的球任意交换. ...
- HDU 5438 Ponds (DFS,并查集)
题意:给定一个图,然后让你把边数为1的结点删除,然后求连通块结点数为奇的权值和. 析:这个题要注意,如果删除一些结点后,又形成了新的边数为1的结点,也应该要删除,这是坑,其他的,先用并查集判一下环,然 ...
- javaScript中"=="和"==="运算符的区别
相同点: 两个运算符均可用于比较两个值是否相等,可允许操作任意类型的操作数,如果操作数相等则返回true,否则返回false. 不同点: "==="运算符也称为严格相等运算符,它用 ...
- 关于 mobile sui a外链 老是出现加载失败的解决办法
mobile sui 框架里面的a本身都绑了了一个ajax方法,ajax只能处理同域,跨域就会出现问题 ,所以mobile sui 中的a如果是外链的话就会出现加载失败的提示,这种明显的bug,让用户 ...
- C++学习之const整理总结
1什么是const? (const类型)常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的.(但可以偷梁换柱进行更新) 2为什么引入const? const 推出的初始 ...
- 通过css代码使边框变圆角(ie9以下浏览器不支持)
(从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期2014-02-11) CSS代码: <style> #myDiv { border-radius: 4px; /*这句就是 ...
- Angular JS 使用的注意事项
标签中ng-app,什么情况需要指定名称,什么时候又不需要呢? 1.ng-app="" <div ng-app="" ng-controller='myC ...
- Android Studio @Bind的用法,自动生成findViewById无需再实例化控件
第一步:app 的build.gradle文件中添加 如下代码: compile 'com.jakewharton:butterknife:7.0.0' 点击Sync Now 同步下载第二步:安装插件 ...