现在的位置: 首页 > 操作系统 > 正文

Python中类的__slots__属性

2020年02月13日 操作系统 ⁄ 共 1753字 ⁄ 字号 评论关闭

默认情况下,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.pyimport timeitclass Foo(object): __slots__ = 'foo',class Bar(object): passslotted = 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上的测试,我这里机(无)智(耻)地取个结果:

# 单位 bytesattrs __slots__ no slots declared + __dict__none 16 64 (+ 280 if __dict__ referenced)one 56 64 + 280two 64 64 + 280six 96 64 + 104822 224 64 + 3352

可以明显看到内存占用减少的情况。

注意事项

__dict__可以理解成类里面存储属性的字典,

    当一个类A继承自一个没有定义__slots__的类B时,A是有__dict__属性,这是再定义__slots__属性没有意义, 不能达到限制内存的作用当尝试给一个定义了__slots__的类,而没有定义__dict__的类设置不在__slots__指定的那些属性时,会导致一个AttributeError其它注意请参照文档

本文永久更新链接地址:http://www.xuebuyuan.com/Linux/2016-12/137776.htm

以上就上有关Python中类的__slots__属性的相关介绍,要了解更多Python类,Python属性,Python中类的__slots__属性,编程,Linux编程,Linux Shell,Android,Android教程,JAVA,C语言,Python,HTML5内容请登录学步园。

抱歉!评论已关闭.