类的__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 ...
随机推荐
- HDU ACM 2121 Ice_cream’s world II (无根最小树形图)
[解题思路]这题先看了NotOnlySuccess的解题思路,即设置虚根再处理的做法:弄了一个上午,再次有种赶脚的感觉~~如果需要找出为什么需要去比所有权值之和更大的数为新增的虚边的话,一开始我理解仅 ...
- git(osx)上的一个git commit无法正确提交的问题
我发现在我修改我自己的文件之后企图使用git commit编辑更加详细的争对这次提交的信息的时候 我mac上的vi编辑器貌似 出现了问题 大概报这个错. error: There was a prob ...
- 解决SQLServer2008 Express远程连接出错的问题[Error: 1326错误]
sqlserver2008 Express版本默认是只能本机测试连接,不能被其他客户端访问,原因是因为Express版本的数据库被连接默认的TCP/IP监听是被关闭的,我们可以做一些设置实现我们的远程 ...
- HDU1002大数加法
大数加法 c++版: #include <map> #include <set> #include <stack> #include <queue> # ...
- 编译安装-PHP
一.编译配置选项2 配置帮助表:2 安装目录:2 交叉编译选项:2 特征选项:3 SAPI模块设置:3 普通参数设置:4 扩展参数:4 PEAR相关选项:9 ZEND相关选项:9 TSRM线程安全资源 ...
- webservice接口的发布
使用xfire-client发布webservice接口: commons-codec-1.3.jar commons-httpclient-3.0.jar 在src 下创建META-INF/xfir ...
- spring中propertyplaceholderconfigurer简介
Spring的框架中为您提供了一个 BeanFactoryPostProcessor 的实作类别: org.springframework.beans.factory.config.PropertyP ...
- LVS 单独完成--负载均衡
原文地址:http://blog.sina.com.cn/s/blog_5f54f0be0101eyiu.html LVS 是通过 IPVS 模块来实现的.IPVS是LVS集群的核心,主要用于完成用户 ...
- 前向否定界定符 python正则表达式不匹配某个字符串 以及无捕获组和命名组(转)
[编辑] 无捕获组和命名组 精心设计的 REs 也许会用很多组,既可以捕获感兴趣的子串,又可以分组和结构化 RE 本身.在复杂的 REs 里,追踪组号变得困难.有两个功能可以对这个问题有所帮助.它们也 ...
- Qt技巧:QProcess与外部程序的调用
项目做到一定阶段,常常须要在原来的project上调用外部程序. Qt为此提供了QProcess类,QProcess可用于完毕启动外部程序,并与之交互通信. 一.启动外部程序的两种方式: (1)一体式 ...