python中的new-style class要求继承Python中的一个内建类型, 一般继承object,也可以继承list或者dict等其他的内建类型。
在python新式类中,可以定义一个变量__slots__,它的作用是阻止在实例化类时为实例分配dict,

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


class base(object):var=9 #类变量def __init__(self):passb=base()
print b.__dict__
b.x=2 #添加实例变量

运行结果:

{ }

{‘x’: 2}

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

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

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

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

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

class base(object):__slots__=('x')var=8def __init__(self):passb=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=11def __init__(self):passb=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的__name __(特殊变量) python中的new-style class要求继承Python中的一个内建类型, 一般继承object,也可以继承list或者dict等其 ...

  2. python __slots__ 详解(上篇)

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

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

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

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

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

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

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

  6. python与golang_Golang与python线程详解及简单实例

    Golang与python线程详解及简单实例 在GO中,开启15个线程,每个线程把全局变量遍历增加100000次,因此预测结果是 15*100000=1500000. var sum int var ...

  7. python 最小二乘法_最小二乘法及其python实现详解

    最小二乘法Least Square Method,做为分类回归算法的基础,有着悠久的历史(由马里·勒让德于1806年提出).它通过最小化误差的平方和寻找数据的最佳函数匹配.利用最小二乘法可以简便地求得 ...

  8. 【python】详解multiprocessing多进程-Pool进程池模块(二)

    [python]详解multiprocessing多进程-process模块(一) [python]详解multiprocessing多进程-Pool进程池模块(二) [python]详解multip ...

  9. 【python】什么是序列,Python序列详解

    什么是序列,Python序列详解 概述 序列索引 序列切片 序列相加 序列相乘 检查元素是否包含在序列中 序列相关的内置函数 range 快速初始化数字列表 概述 所谓序列,指的是一块可存放多个值的连 ...

最新文章

  1. Nginx学习笔记(一)
  2. python标准库os中用来列出_Python 标准库 os 中用来列出指定文件夹中的文件和子文件夹列表的方式是listdir()。_高职高专数字资源平台答案_学小易找答案...
  3. js中的时间与毫秒数互相转换
  4. LeetCode 1871. 跳跃游戏 VII(贪心)
  5. python怎么输出图片_python输出彩色图片python 时间处理
  6. JAVA中commons-collections-3.2.1.jar包是干什么用的?
  7. 设置iis支持wap服务
  8. BZOJ3123:[SDOI2013]森林——题解
  9. 信鸽推送(Android和iOS):详细流程+问题解决
  10. 2022年6月青少年软件编程(Python)等级考试试卷(一级)
  11. Python 合并两个或多个pdf文件(获取pdf文件指定页)
  12. Fast Walsh-Hadamard Transform (快速沃尔什变换)
  13. 计算机 人脑 发热 ppt,人脑即电脑,疯狂的大脑进化史,大脑科学的革命
  14. matlab图像自动标注程序,基于MATLAB/GUI的图像语义自动标注系统
  15. ESP8266 AP模式建立服务器
  16. peU盘ud区和efi区如何共用wim文件
  17. SAP工具箱通用条件/加点率配置
  18. rke 部署的时候报错:Failed to set up SSH tunneling for host
  19. OSI七层模型的功能及协议
  20. 计算机的广泛应用让我们摆脱了很多文书工作,英语汉英翻译题.doc

热门文章

  1. css 预编译处理器 - Stylus
  2. 哈希函数在密码学中的应用
  3. 国内永久免费下载免费网站监控服务测评:阿里云监控、百度云观测等
  4. 虚拟串口服务器原码,虚拟串口的完整源代码
  5. [C语言] [试题详解] 求1000之内的所有 完数
  6. 保存文件弹出框-选择路径
  7. 四面向对象的学习、反射、异常处理
  8. 移远BC35-G模组(NB-IoT 通信模组)AT指令测试 UDP 通信过程
  9. PHP爬虫音乐,PHP 爬虫———爬取网易云音乐歌单
  10. 百度APP移动端网络深度优化实践分享(一):DNS优化篇