参考链接: Python的__name __(特殊变量)

python中的new-style class要求继承Python中的一个内建类型,

一般继承object,也可以继承list或者dict等其他的内建类型。

在python新式类中,可以定义一个变量__slots__,它的作用是阻止在实例化类时为实例分配dict,

默认情况下每个类都会有一个dict,通过__dict__访问,这个dict维护了这个实例的所有属性,举例如下:

class base(object):

var=9 #类变量

def __init__(self):

pass

b=base()

print b.__dict__

b.x=2 #添加实例变量

print b.__dict__运行结果:

{ }

{'x': 2}

可见:实例的dict只保持实例的变量,对于类的属性是不保存的,类的属性包括变量和函数。

由于每次实例化一个类都要分配一个新的dict,因此存在空间的浪费,因此有了__slots__。

__slots__是一个元组,包括了当前能访问到的属性。

当定义了slots后,slots中定义的变量变成了类的描述符,相当于java,c++中的成员变量声明,

类的实例只能拥有slots中定义的变量,不能再增加新的变量。注意:定义了slots后,就不再有dict。如下:

class base(object):

__slots__=('x')

var=8

def __init__(self):

pass

b=base()

b.x=88 #添加实例变量

print b.x

#b.y=99 #无法添加slots之外的变量 (AttributeError: 'base' object has no attribute 'y')

#print b.__dict__ #定义了__slots__后,就不再有__dict__ (AttributeError: 'base' object has no attribute '__dict__')运行结果:

88

如果类变量与slots中的变量同名,则该变量被设置为

readonly!!!如下:

class base(object):

__slots__=('y')

y=22 # y是类变量,y与__slots__中的变量同名

var=11

def __init__(self):

pass

b=base()

print b.y

print base.y

#b.y=66 #AttributeError: 'base' object attribute 'y' is read-only运行结果:

22

22

Python是一门动态语言,可以在运行过程中,修改实例的属性和增删方法。一般,任何类的实例包含一个字典__dict__,

Python通过这个字典可以将任意属性绑定到实例上。有时候我们只想使用固定的属性,而不想任意绑定属性,

这时候我们可以定义一个属性名称集合,只有在这个集合里的名称才可以绑定。__slots__就是完成这个功能的。

class test_slots(object):

__slots__='x','y'

def printHello(self):

print 'hello!'

class test(object):

def printHello(self):

print 'hello'

print dir(test_slots) #可以看到test_slots类结构里面包含__slots__,x,y

print dir(test)#test类结构里包含__dict__

print '**************************************'

ts=test_slots()

t=test()

print dir(ts) #可以看到ts实例结构里面包含__slots__,x,y,不能任意绑定属性

print dir(t) #t实例结构里包含__dict__,可以任意绑定属性

print '***************************************'

ts.x=11 #只能绑定__slots__名称集合里的属性

t.x=12 #可以任意绑定属性

print ts.x,t.x

ts.y=22 #只能绑定__slots__名称集合里的属性

t.y=23  #可以任意绑定属性

print ts.y,t.y

#ts.z=33 #无法绑定__slots__集合之外的属性(AttributeError: 'test_slots' object has no attribute 'z')

t.z=34 #可以任意绑定属性

print t.z 运行结果:

['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '

__slots__', '__str__', '__subclasshook__', 'printHello', '

x', 'y']

['__class__', '__delattr__', '

__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printHello']

**************************************

['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '

__slots__', '__str__', '__subclasshook__', 'printHello', '

x', 'y']

['__class__', '__delattr__', '

__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printHello']

***************************************

11 12

22 23

34

正如上面所说的,默认情况下,Python的新式类和经典类的实例都有一个

dict来存储实例的属性。这在一般情况下还不错,而且非常灵活,

乃至在程序中可以

随意设置新的属性。但是,对一些在”编译”前就知道有几个固定属性的小class来说,这个dict就有点浪费内存了。

当需要创建大量实例的时候,这个问题变得尤为突出。一种解决方法是在

新式类中定义一个__slots__属性。

__slots__声明中包含若干实例变量,并为每个实例预留恰好足够的空间来保存每个变量;这样Python就不会再使用dict,从而节省空间。

【使用memory_profiler模块,memory_profiler模块是在逐行的基础上,测量代码的内存使用率。尽管如此,它可能使得你的代码运行的更慢。使用装饰器@profile来标记哪个函数被跟踪。】 下面,我们看一个例子:

from  memory_profiler import profile

class A(object): #没有定义__slots__属性

def __init__(self,x):

self.x=x

@profile

def main():

f=[A(523825) for i in range(100000)]

if __name__=='__main__':

main()运行结果,如下图:

第2列表示该行执行后Python解释器的内存使用情况,

第3列表示该行代码执行前后的内存变化。

在没有定义__slots__属性的情况下,该代码共使用了20.8MiB内存。

从结果可以看出,内存使用是以MiB为单位衡量的,表示的mebibyte(1MiB = 1.05MB)

from  memory_profiler import profile

class A(object):#定义了__slots__属性

__slots__=('x')

def __init__(self,x):

self.x=x

@profile

def main():

f=[A(523825) for i in range(100000)]

if __name__=='__main__':

main()运行结果,如下图:

可以看到,在定义了__slots__属性的情况下,该代码共使用了6.1MiB内存,比上面的20.8MiB节省了很多内存!

综上所述,在确定了

类的属性固定的情况下,可以

使用__slots__来优化内存。

提醒:不要贸然进行这个优化,把它用在所有地方。这种做法不利于代码维护,而且只有生成数以千计的实例的时候才会有明显效果。

(完)

[转载] python __slots__ 详解(上篇)相关推荐

  1. python __slots__ 详解(上篇)

    python中的new-style class要求继承Python中的一个内建类型, 一般继承object,也可以继承list或者dict等其他的内建类型. 在python新式类中,可以定义一个变量_ ...

  2. python __slots__ 详解

    python中的new-style class要求继承Python中的一个内建类型, 一般继承object,也可以继承list或者dict等其他的内建类型. 在python新式类中,可以定义一个变量_ ...

  3. [转载] python super详解

    参考链接: Python super() 说到 super, 大家可能觉得很简单呀,不就是用来调用父类方法的嘛.如果真的这么简单的话也就不会有这篇文章了,且听我细细道来.? 约定 在开始之前我们来约定 ...

  4. python多线程详解 Python 垃圾回收机制

    文章目录 python多线程详解 一.线程介绍 什么是线程 为什么要使用多线程 总结起来,使用多线程编程具有如下几个优点: 二.线程实现 自定义线程 守护线程 主线程等待子线程结束 多线程共享全局变量 ...

  5. Python数据类型详解03

    原文博客地址: Python数据类型详解03 第一篇Python数据类型详解01中主要介绍了Python中的一些常用的数据类型的基础知识 第二篇Python数据类型详解02文章中, 详细介绍了数字(N ...

  6. IOS视频编辑功能详解上篇-添加水印

    前言 用代码在简单视频编辑中,主要就是加美颜.水印(贴图).视频截取.视频拼接.音视频的处理,在美颜中,使用GPUImage即可实现多种滤镜.磨皮美颜的功能,并且可以脸部识别实时美颜等功能,这个有很多 ...

  7. python区块链开发_Fabric区块链Python开发详解

    Hyperledger Fabric是最流行的联盟区块链平台.Fabric区块链Python开发详解课程 涵盖Fabric区块链的核心概念.Fabric网络搭建.Node链码开发.Python应用开发 ...

  8. python装饰器setter_第7.27节 Python案例详解: @property装饰器定义属性访问方法getter、setter、deleter...

    上节详细介绍了利用@property装饰器定义属性的语法,本节通过具体案例来进一步说明. 一.    案例说明 本节的案例是定义Rectangle(长方形)类,为了说明问题,除构造函数外,其他方法都只 ...

  9. 【python】详解类class的继承、__init__初始化、super方法

    原文链接; https://blog.csdn.net/brucewong0516/article/details/79121179?utm_medium=distribute.pc_relevant ...

最新文章

  1. 文件存储服务器英文,文件存储服务器
  2. 函数的凹凸性证明_判断复杂函数的凹凸性
  3. 平滑重启_swoole服务平滑重启
  4. Python基础(10)--数字
  5. SVD分解算法及其应用
  6. mysql hive索引_Hive数据仓库--HiveQL视图和索引
  7. 二分查找(划分时左右元素个数不相等)解析+代码
  8. 【转】03.Dicom 学习笔记-DICOM C-Get 消息服务
  9. LCD1602液晶显示
  10. Bailian2980 大整数乘法【大数】
  11. 图像局部特征(三)--FAST角点检测子
  12. Python游戏开发入门2 壁球小游戏与图像的基本使用
  13. jq实现表格冻结窗格的样式
  14. 人工智能的局限性--王垠
  15. SV-- event(二)
  16. 【MySQL】测试题02
  17. 图书采购管理系统分析
  18. 【PTA】到底是不是太胖了
  19. 最新计算机cpu简介,计算机cpu的类型是什么?计算机CPU分类简介
  20. 计算机专业英语1500词TXT,电脑专业英语1500词

热门文章

  1. 堆排序算法---属于选择排序
  2. matlab画图plot设置字体_R语言科研画图字体格式设置
  3. sql中in与php数组,格式化SQL“IN”子句的PHP数组
  4. 实验报告: 线性表的基本操作及应用
  5. java 对象复制字段_利用Java反射机制实现对象相同字段的复制
  6. linux中如何查看某个端口是否被占用,LINUX中如何查看某个端口是否被占用
  7. python3.8使用方法_python3.8新特性
  8. golang 安全的tcp server_Go 语言使用 TCP_NODELAY 控制发包流量
  9. pythonwrite连续写入_python文件写入write()的操作
  10. 各种损失损失函数的使用场景和使用方法:KL散度