Python中__slots__属性介绍与基本使用方法


Posted in Python onSeptember 05, 2018

简介

在廖雪峰的python网站上,他是这么说的

python是动态语言,它允许程序在执行过程中动态绑定属性或者方法(使用MethodTpye)。

某个实例在执行过程中绑定的属性跟方法,仅在该实例中有效,其他同类实例是没有的。

可以通过给class绑定属性/方法,来给所有实例绑定属性/方法:

Student.name = ''
Student.set_score = set_score

而如果使用__slots__,它仅允许动态绑定()里面有的属性

例如,下面这样会报错

class Student():
__slots__ = ('name', 'age')

S1 = Student()
S1.name = 'Jack' # ok!
S1.score = 123 # error!

但是我觉得很奇怪,仅有这一个作用吗?于是我再查了其他资料,发现这个函数可以很可观地节约内存,下面来一起看看详细的介绍吧。

__slots__允许我们声明并限定类成员,并拒绝类创建__dict__和__weakref__属性以节约内存空间。

Python是动态语言,对于普通的类,可以为类实例赋值任何属性,这些属性会存储在__dict__中:

>>> class Student(object):
... pass
... 
>>> Abey = Student()
>>> Abey.name = 'Abey'
>>> Abey.__dict__
{'name': 'Abey'}

这样的特性带来两个问题:

  • 数据通过字典(Hash)存储所占用的空间较大
  • 如何禁止随意生成类属性

当然,__slots__就能解决这两个问题。通过__slots__属性限定类属性的创建:

>>> class Student(object):
... __slots__ = ('name', 'age')
... 
>>> Abey = Student()
>>> Abey.name = 'Abey'
>>> Abey.gender = 'Female'
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'gender'
>>> Abey.__dict__
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'Student' object has no attribute '__dict__'

可以看到,在定义了__slots__变量后,Student类实例已经不能随意创建不在__slots__定义内的属性gender,同时实例中也不再有__dict__结构。

用法

继承树

__slots__在继承中有两种表现:

  • 子类未声明__slots__时,不继承父类的__slots__,即此时子类实例可以随意赋值属性
  • 子类声明__slots__时,继承父类的__slots__,即此时子类的__slots__为其自身+父类的__slots__

以下面的父类为例:

>>> class Student(object):
... __slots__ = ('name', 'age')
...

创建一个子类不声明__slots__,该类实例可以创建父类__slots__限定之外的属性gender:

>>> class SubStudent(Student):
... pass
... 
>>> Bob = SubStudent()
>>> Bob.gender = 'Male'
>>> Bob.__dict__
{'gender': 'Male'}

而创建一个声明__slots__的子类,该类属性则只能创建父类__slots__+自身__slots__限定的属性:

>>> class SubStudent2(Student):
... __slots__ = 'gender'
... 
>>> Cathy = SubStudent2()
>>> Cathy.gender = 'Female'
>>> Cathy.name = 'Cathy'
>>> Cathy.teacher = 'Mrs. Wang'
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'SubStudent2' object has no attribute 'teacher'

注意:子类的__slots__本身已经继承自父类,无需重复声明父类已声明的属性。例如上例,重复声明会多占用内存空间:

>>> class SubStudent3(Student):
... __slots__ = ('name', 'age', 'gender')
... 
>>> from sys import getsizeof
>>> getsizeof(Student()), getsizeof(SubStudent2()), getsizeof(SubStudent3())
(56, 64, 80)

性能对比

我们为什么要使用__slots__呢?

更快速地赋值属性

参考Stack Overflow回答中给出的数据:

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

得到测试结果为:

>>> min(timeit.repeat(get_set_delete_fn(slotted)))
0.2846834529991611
>>> min(timeit.repeat(get_set_delete_fn(not_slotted)))
0.3664822799983085

可以看到,在相同的环境(Ubuntu)下,slots为Python3.5带来了接近30%的赋值速度提升:

节约内存空间

>>> 0.3664822799983085 / 0.2846834529991611
1.2873325658284342

由于不使用__dict__存储对象的属性,__slots__在一些场景下能够节约极大的内存空间。具体数据可以查看参考中的回答链接,不赘述。

参考

[1] Usage of __slots__? ,  Aaron Hall, Stack Overflow

推荐阅读

[1] Data model , Python Document

[2] python __slots__ 使你的代码更加节省内存 , david_bj, 51CTO

[3] 使用__slots__ , 廖雪峰

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python实现建立SSH连接的方法
Jun 03 Python
python3实现暴力穷举博客园密码
Jun 19 Python
浅谈pandas中shift和diff函数关系
Apr 08 Python
Python2和Python3之间的str处理方式导致乱码的讲解
Jan 03 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
Jan 26 Python
python wav模块获取采样率 采样点声道量化位数(实例代码)
Jan 22 Python
python计算Content-MD5并获取文件的Content-MD5值方式
Apr 03 Python
python Canny边缘检测算法的实现
Apr 24 Python
python对接ihuyi实现短信验证码发送
May 10 Python
Django中和时区相关的安全问题详解
Oct 12 Python
matplotlib常见函数之plt.rcParams、matshow的使用(坐标轴设置)
Jan 05 Python
Python中的变量与常量
Nov 11 Python
python使用xlrd和xlwt读写Excel文件的实例代码
Sep 05 #Python
python 3调用百度OCR API实现剪贴板文字识别
Sep 04 #Python
Python实现监控键盘鼠标操作示例【基于pyHook与pythoncom模块】
Sep 04 #Python
Python使用pyautogui模块实现自动化鼠标和键盘操作示例
Sep 04 #Python
Python PyAutoGUI模块控制鼠标和键盘实现自动化任务详解
Sep 04 #Python
selenium+python实现自动化登录的方法
Sep 04 #Python
python使用scrapy发送post请求的坑
Sep 04 #Python
You might like
把77A收信机改造成收音机
2021/03/02 无线电
利用php生成验证码
2017/02/23 PHP
PHP5.6读写excel表格文件操作示例
2019/02/26 PHP
JS在可编辑的div中的光标位置插入内容的方法
2014/11/20 Javascript
js实现仿百度瀑布流的方法
2015/02/05 Javascript
jquery使用animate方法实现控制元素移动
2015/03/27 Javascript
js+html5绘制图片到canvas的方法
2015/06/05 Javascript
PHP+MySQL+jQuery随意拖动层并即时保存拖动位置实例讲解
2015/10/09 Javascript
JavaScript中获取纯正的undefined的方法
2016/03/06 Javascript
详解Angularjs中的依赖注入
2016/03/11 Javascript
浅谈几种常用的JS类定义方法
2016/06/08 Javascript
jQuery中JSONP的两种实现方式详解
2016/09/26 Javascript
JS限定手机版中图片大小随分辨率自动调整的方法
2016/12/05 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
javascript九宫格图片随机打乱位置的实现方法
2017/03/15 Javascript
使用 Node.js 对文本内容分词和关键词抽取
2017/05/27 Javascript
JavaScript实现删除数组重复元素的5种常用高效算法总结
2018/01/18 Javascript
node thread.sleep实现示例
2018/06/20 Javascript
详解vue中组件参数
2018/07/09 Javascript
微信小程序开发实现的选项卡(窗口顶部/底部TabBar)页面切换功能图文详解
2019/05/14 Javascript
windows下create-react-app 升级至3.3.1版本踩坑记
2020/02/17 Javascript
Vue项目vscode 安装eslint插件的方法(代码自动修复)
2020/04/15 Javascript
Python退火算法在高次方程的应用
2018/07/26 Python
Python3中的最大整数和最大浮点数实例
2019/07/09 Python
使用 Python 快速实现 HTTP 和 FTP 服务器的方法
2019/07/22 Python
python按照list中字典的某key去重的示例代码
2020/10/13 Python
美国羽绒床上用品第一品牌:Pacific Coast
2018/08/25 全球购物
Bose美国官网:购买Bose耳机和音箱
2019/03/10 全球购物
实习自我鉴定范文
2013/10/30 职场文书
学校关爱留守儿童活动方案
2014/08/27 职场文书
商务英语专业大学生职业生涯规划书
2014/09/14 职场文书
单位租房协议范本
2014/12/03 职场文书
结婚通知短信怎么写
2015/04/17 职场文书
2016暑期社会实践心得体会范文
2016/01/14 职场文书
python 如何在 Matplotlib 中绘制垂直线
2021/04/02 Python
mysq启动失败问题及场景分析
2021/07/15 MySQL