类的__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 ...
随机推荐
- 第三百零八至三百二十天 how can I 坚持
十三天..2月4号至2月16号,好快,假期还没开始就结束了.一一回忆下. 2月4号,腊月二十六,最后一天上班,没多大事,好像是玩了一天,东月回家,貌似路上好折腾,晚上D401,和她聊了一路,也聊了好多 ...
- Xtrabackup之innobackupex备份恢复详解(转)
add by zhj:对于Xtrabackup2.2来说,已经解决了本文结尾提到的那个bug,当使用--copy-back时,同时加--force-non-empty-directories 即可.这 ...
- HD1005Number Sequence
Number Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- svg base64
好多h5页面有出现data:image/png;base64,后面跟了一串类似乱码的字母 查了下原来这也是svg或者是图片 <img src=“data:image/png;base64,iVB ...
- 陕西中际现代:基于自适应算法的PLC滴灌控制系统
基于自适应算法的PLC滴灌控制系统 陕西中际现代包装科技有限公司滴灌部 1.介绍 水资源正在成为一种珍贵的资源.城镇的市民使用成千上万立方的水来浇灌花园和绿地.他们依赖于使用固定灌溉计划的控制器.而这 ...
- jqeuery $.ajax 与后台jsone交互
============================action后台,我这里是SpringMVC================================================@C ...
- 递归模式学习(recursion)
所谓递归,就是方法调用自身.对于递归模式来说,要有一个出口来让递归结束,避免出现死循环. 实例全排列: 从n中拿出m个元素进行排列,当n==m时为全排列. 利用递归就是:把n个元素轮流放入第一个位置, ...
- socket编写简单回显server
socket在公司代码中应用比较广,比如接口调用的IPCRPC机制,经常看到这样的代码,但是一直也没有动手写过. 在某个比较大的进程中创建一个子进程,由于父子进程复制会浪费内存,可以将创建进程的命令通 ...
- android ListView中的Item有Button时候点击异常处理
1.当ListView中有Button的时候往往会遇到很多问题,比较常见的一个问题是: 假设:在ListView中有N个Item当点击其中某个Item中的Button的时候,需要改变当前Button的 ...
- 如何让DIV相对于body水平和垂直居中
我们在设计页面的时候,经常要把DIV居中显示,而且是相对页面窗口水平和垂直方向居中显示,如让登录窗口居中显示.我们传统解决的办法是用纯CSS来让DIV居中.在本文中,我将给大家讲述如何用CSS和jQu ...