为什么有"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__可以理解成类里面存储属性的字典,

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

    其它注意请参照文档

类的__slots__属性的更多相关文章

  1. python类的__slots__属性、__del__属性、上下文(__enter__和__exit__)、

    常规情况下,类的属性字典是共享的,而实例的字典是独立的.如果一个类的属性较少,但是拥有很多的实例,这些实例的属性字典会占用较多的内存空间.对这样的类来说,为了节省内存空间,可以使用__slots__类 ...

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

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

  3. Python 类的高级属性(可选)

    1.slots实例:限制类的实例有合法的属性集,只有__slots__属性列表中的属性才可能成为实例属性. 对象的实例通常没有一个属性字典,可以在__slots__列表中包含一个属性字典__dict_ ...

  4. __slots__属性

    使用__slots__时,子类不受影响 class Person(object): __slots__ = ("name","age") def __str__ ...

  5. Python的动态语言特性; __slots__属性

    python是动态语言 1. 动态语言的定义 动态编程语言 是 高级程序设计语言 的一个类别,在计算机科学领域已被广泛应用.它是一类 在运行时可以改变其结构的语言 :例如新的函数.对象.甚至代码可以被 ...

  6. id选择器、类选择器、属性选择器

    在网页编辑时,通常要对样式进行各种设置.我们借助CSS样式设计中的选择器,就能很好很方便的对它们进行管理和设置了. 今天,跟大家分享一下几个常用的选择器:id选择器.类选择器.属性选择器. id选择器 ...

  7. JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  8. 转载:java 中对类中的属性使用set/get方法的意义和用法

    经常看到有朋友提到类似:对类中的属性使用set/get方法的作用?理论的回答当然是封闭性之类的,但是这样对我们有什么作用呢?为什么要这样设计?我直接使用属性名来访问不是更直接,代码更简洁明了吗?下面我 ...

  9. java基础—继承题目:编写一个Animal类,具有属性:种类;具有功能:吃、睡。定义其子类Fish

    编写一个Animal类,具有属性:种类:具有功能:吃.睡.定义其子类Fish package zhongqiuzuoye; public class Animal { //属性 private Str ...

随机推荐

  1. 《Java数据结构与算法》笔记-CH5-链表-1单链表

    /** * Link节点 * 有数据项和next指向下一个Link引用 */ class Link { private int iData;//数据 private double dData;//数据 ...

  2. 检查 CPU 是否支持二级地址转换 - 摘自网络

    Windows 8 Consumer Preview 于2月正式发布,随后 Windows Server 8 Beta 也公布了下载.整体对比,Windows 8 在硬件方面的要求并不高,其最低硬件需 ...

  3. MVC中过虑特殊字符检测

    [ValidateInput(false)] [HttpPost] public ActionResult Modify(Models.BlogArticle model) { //...... } ...

  4. tomcat的host配置

    本机 etc\hosts 首先了解C:\WINDOWS\system32\drivers\etc\hosts文件配置 127.0.0.1 static1.ezsins.com #adoble ps c ...

  5. django 命名空间详解

    include(module[, namespace=None, app_name=None ]) include(pattern_list) include((pattern_list, app_n ...

  6. LabVIEW数据记录和存储—XML文件

    XML(eXtensible Markup Language)是一种目前广泛使用的数据传输和存储的格式,其本质上是一种文本文件,可以使用任何一个文本编辑工具打开和修改.类似于HTML,XML被设计为具 ...

  7. ubuntu14.04恢复系统默认中文字体

    今天 Ubuntu14.04已发布就进行了更新,在配置过程中,无意安装了某些中文字体,导致系统的中文字体极其难看,根据网上说的修改配置文件和tweak 修改的方法都不能解决,最终找到的解决办法(htt ...

  8. c++/java/c# 几种编程语言的指针、引用比较

    前一段时间,我在 cnblogs 别人的博客中,谈到: java 中的引用/指针,与 c++/C# 中的引用/指针不是一个概念. Java 引用,相当于 c++ 指针(fun3).Java 引用可以赋 ...

  9. 解决数据库datatime数据在DataGridView里不显示秒的解决

    在数据库中正确显示有分有秒,到dataset里的时候也有,但绑定到DataGridView里的时候就没有秒,解决办法: dataGridView1.Columns["record_time& ...

  10. session与缓存

    分布式系统开发常见问题-1. session的复制与共享 2. 分布式缓存的设计 1. session的复制与共享 在web应用中,为了应对大规模访问,必须实现应用的集群部署.要实现集群部署主要需要实 ...