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通过apply使用元祖和列表调用函数实例
May 26 Python
在Lighttpd服务器中运行Django应用的方法
Jul 22 Python
python3.5+tesseract+adb实现西瓜视频或头脑王者辅助答题
Jan 17 Python
10 分钟快速入门 Python3的教程
Jan 29 Python
Python爬虫动态ip代理防止被封的方法
Jul 07 Python
详解python列表(list)的使用技巧及高级操作
Aug 15 Python
python 多进程并行编程 ProcessPoolExecutor的实现
Oct 11 Python
基于python及pytorch中乘法的使用详解
Dec 27 Python
matplotlib 对坐标的控制,加图例注释的操作
Apr 17 Python
Pycharm安装并配置jupyter notebook的实现
May 18 Python
基于python实现计算两组数据P值
Jul 10 Python
Python之matplotlib绘制折线图
Apr 13 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
从MySQL数据库表中取出随机数据的代码
2007/09/05 PHP
PHP中$_SERVER的详细参数与说明
2008/07/29 PHP
一步一步学习PHP(6) 面向对象
2010/02/16 PHP
本地计算机无法启动Apache故障处理
2014/08/08 PHP
PHP strip_tags() 去字符串中的 HTML、XML 以及 PHP 标签的函数
2016/05/22 PHP
Zend Framework处理Json数据方法详解
2016/12/09 PHP
php实现自定义中奖项数和概率的抽奖函数示例
2017/05/26 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
2017/09/30 PHP
PHP内置函数生成随机数实例
2019/01/18 PHP
PHP大文件及断点续传下载实现代码
2020/08/18 PHP
JS中实现简单Formatter函数示例代码
2014/08/19 Javascript
$(&quot;&quot;).click与onclick的区别示例介绍
2014/09/25 Javascript
jQuery实现的在线答题功能
2015/04/12 Javascript
jQuery点击其他地方时菜单消失的实现方法
2016/04/22 Javascript
JS简单实现移动端日历功能示例
2016/12/28 Javascript
解决AngualrJS页面刷新导致异常显示问题
2017/04/20 Javascript
一篇文章,教你学会Vue CLI 插件开发
2019/04/17 Javascript
Vue搭建后台系统需要注意的问题
2019/11/08 Javascript
JavaScript字符串处理常见操作方法小结
2019/11/15 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
2020/12/07 Vue.js
[01:11:35]Liquid vs LGD 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python中MYSQLdb出现乱码的解决方法
2014/10/11 Python
python调用java模块SmartXLS和jpype修改excel文件的方法
2015/04/28 Python
Python实现快速多线程ping的方法
2015/07/15 Python
Python探索之实现一个简单的HTTP服务器
2017/10/28 Python
pytorch实现用CNN和LSTM对文本进行分类方式
2020/01/08 Python
Python 列表的清空方式
2020/01/13 Python
解决Python发送Http请求时,中文乱码的问题
2020/04/30 Python
基于Python词云分析政府工作报告关键词
2020/06/02 Python
环境工程求职简历的自我评价范文
2013/10/24 职场文书
会计专业自荐信范文
2013/12/02 职场文书
简短证婚人证婚词
2014/01/09 职场文书
幼儿园教育教学反思
2014/01/31 职场文书
硕士研究生求职自荐信范文
2014/03/11 职场文书
百货商场楼层班组长竞聘书
2014/03/31 职场文书
python如何将mat文件转为png
2022/07/15 Python