一句话说明

__slots__是用来限制实例的属性的,__slots__可以规定实例是否应该有__dict__属性;__slots__不能限制类的属性。

只有__slots__列表内的这些变量名可赋值为实例属性。

class A:
__slots__=['name']
def __init__(self):
self.name='js'
self.age=22
a=A()

运行结果:

Traceback (most recent call last):
File "a.py", line 6, in <module>
a=A()
File "a.py", line 5, in __init__
self.age=22
AttributeError: 'A' object has no attribute 'age'

__slots__只是限制实例,对类对象没有影响

class A:
__slots__=['name','city']
age=22
def __init__(self):
self.name='js'
a=A()
print('A __slots__: ', A.__slots__)
print('a __slots__: ', a.__slots__)
print('A __dict__: ', A.__dict__)
print('a __dict__: ', a.__dict__)

运行结果如下:

A __slots__:  ['name', 'city']
a __slots__: ['name', 'city']
#事实上,所有定义在__slots__中的属性都会放置在类的__dict__当中,即使没有使用的属性(city)也是如此。
#而当实例需要取对象时,总是会先到类的__dict__中进行检查,如果类的__dict__中的属性是一个对象且该对象对属性的读取做了一些限制,那么就会直接影响到实例是否能够调用该属性。__slots__的工作原理是如此,后面介绍的描述符类亦是如此。
#在类的__dict__中,也会存入__slots__属性。
A __dict__: {'age': 22, '__init__': <function A.__init__ at 0x7f2ae9be67b8>, 'name': <member 'name' of 'A' objects>, 'city': <member 'city' of 'A' objects>, '__slots__': ['name', 'city'], '__module__': '__main__', '__doc__': None}
#当我们试图调用a.__dict__时,出现错误,因为该属性没有出现在__slots__中,所以禁止赋值或者访问。
Traceback (most recent call last):
File "a.py", line 10, in <module>
print('a __dict__: ', a.__dict__)
AttributeError: 'A' object has no attribute '__dict__'

可以同时存在__slots__和__dict__吗?

可以,如果把__dict__属性存入__slots__中,那么就允许使用__dict__属性了。

这时,如果所有__slots__中定义的属性存在__slots__中,如果没有定义的属性,那么存在__dict__中,从而实现属性的分别管理。

dir函数获取所有定义在__slots____dict__中的属性。或者通过list(getattr(X, 'dict', [])) + getattr(X, 'slots', [])来得到所有的属性。

class A:
__slots__=('name','city','__dict__')
def __init__(self):
self.name='js'
self.age=22
a=A()
print('A __slots__: ', A.__slots__)
print('a __slots__: ', a.__slots__)
print('A __dict__: ', A.__dict__)
print('a __dict__: ', a.__dict__)

运行结果如下:

A __slots__:  ('name', 'city', '__dict__')
a __slots__: ('name', 'city', '__dict__')
#连__dict__都会保存在类的__dict__中,且属性值是一个object。
A __dict__: {'city': <member 'city' of 'A' objects>, 'name': <member 'name' of 'A' objects>, '__module__': '__main__', '__doc__': None, '__init__': <function A.__init__ at 0x7f540bb787b8>, '__slots__': ('name', 'city', '__dict__'), '__dict__': <attribute '__dict__' of 'A' objects>}
#由于现在age没有出现在__slots__中,且允许存在__dict__,所以属性age出现在实例本身的__dict__中。
a __dict__: {'age': 22}

如果子类中没有__slots__,但是超类中有...

class Super:
__slots__=['name']
pass
class Sub(Super):
def __init__(self):
self.name='js'
self.age=22
a=Sub()
print('Sub __slots__: ', Sub.__slots__)
print('a __slots__: ', a.__slots__)
print('Sub __dict__: ', Sub.__dict__)
print('a __dict__: ', a.__dict__)

运行结果如下:

#顺利继承到了Super的__slots__属性
Sub __slots__: ['name']
a __slots__: ['name']
#此时Python用了大量的黑暗魔法,这时我们看到Sub的__dict__中居然出现了__dict__属性,且值为特殊的对象,相当于Sub.__slots__=Super.__slots__+['__dict__'],从而实现如果在__slots__中出现的属性存在__slots__中,没有出现的存在Sub的实例的__dict__中。
Sub __dict__: {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Sub' objects>, '__weakref__': <attribute '__weakref__' of 'Sub' objects>, '__doc__': None, '__init__': <function Sub.__init__ at 0x7fc35f7036a8>}
#我们确实看到了age存在了子类的实例的__dict__中。
a __dict__: {'age': 22}

如果子类和父类都有__slots__...

class Super:
__slots__=['name','age']
class Sub(Super):
__slots__=['city']
print('Sub __slots__: ', Sub.__slots__)
print('Sub __dict__: ', Sub.__dict__)

运行结果如下:

#父类中的__slots__没有对子类产生影响
Sub __slots__: ['city']
#再次证明了上面的说法,如果一定需要父类的__slots__进行叠加,那么需要手动设置为__slots__=Super.__slots__ + ['city'],所以可以看出Python通过了大量的黑暗魔法,从而达到__slots__不具有常规的继承特性。
Sub __dict__: {'__slots__': ['city'], '__module__': '__main__', 'city': <member 'city' of 'Sub' objects>, '__doc__': None}

如果一个子类继承自一个没有__slots__的超类...

如果一个子类继承自一个没有__slots__的超类,那么超类的__dict__属性总是可以访问的,使得子类中的一个__slots__无意义。

留给你自己验证一下吧。

总结

  1. __slots__用来设计成对实例的__dict__的限制,只有__dict__出现在__slots__中,实例才会有__dict__属性。

    否则,只有出现在__slots__中的属性才可以被使用。
  2. Python特意设计成__slots__没有常规的继承特性,所以只有超类具有__slots__且其__dict__属性没有出现在其中,这时子类的__slots__才有意义,且子类的__slots__不继承父类的__slots__

Python属性、方法和类管理系列之----__slots__属性的更多相关文章

  1. Python属性、方法和类管理系列之----属性初探

    在学习dict的时候,肯定听过dict是Python中最重要的数据类型,但是不一定知道为什么.马上你就会明白原因了. Python中从模块.到函数.到类.到元类,其实主要管理方法就是靠一个一个的字典. ...

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

    什么是描述符类? 根据鸭子模型理论,只要具有__get__方法的类就是描述符类. 如果一个类中具有__get__和__set__两个方法,那么就是数据描述符,. 如果一个类中只有__get__方法,那 ...

  3. Python属性、方法和类管理系列之----元类

    元类的介绍 请看位于下面网址的一篇文章,写的相当好. http://blog.jobbole.com/21351/ 实例补充 class Meta(type): def __new__(meta, c ...

  4. python 面向对象静态方法、类方法、属性方法、类的特殊成员方法

    静态方法:只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性. 在类中方法定义前添加@staticmethod,该方法就与类中的其他(属性,方法)没有关系,不能通过实例化类调用方法使用 ...

  5. Python 属性方法、类方法、静态方法、 特殊属性__doc__ (内建属性)

    总结:和类的关联性讲:属性方法>类方法>静态方法 属性方法@property:仅仅是调用方式不用+括号. 类方法@classmethod:访问不了累的属性变量,只可以访问类变量. 静态方法 ...

  6. python特殊方法定制类

    #coding:utf-8class RoundFloat(object): def __init__(self,val): assert isinstance(val, float),"v ...

  7. ES6 属性方法简写一例:vue methods 属性定义方法

    const o = { method() { return "Hello!"; } }; // 等同于 const o = { method: function() { retur ...

  8. Python类(六)-静态方法、类方法、属性方法

    静态方法 通过@staticmethod来定义,静态方法在类中,但在静态方法里访问不了类和实例中的属性,但静态方法需要类来调用 # -*- coding:utf-8 -*- __author__ = ...

  9. python类属性和类方法(类的结构、实例属性、静态方法)

    类属性和类方法 目标 类的结构 类属性和实例属性 类方法和静态方法 01. 类的结构 1.1 术语 —— 实例 使用面相对象开发,第 1 步 是设计 类 使用 类名() 创建对象,创建对象 的动作有两 ...

随机推荐

  1. 深入理解计算机系统第二版习题解答CSAPP 2.17

    假设w=4,我们能给每个可能的十六进制数字赋予一个数值,假设用一个无符号或者补码表示.完成下表: x 无符号(B2U(x)) 补码(B2T(x)) 十六进制 二进制 0xE 1110 14 -2 0x ...

  2. I2C总线协议的总结介绍

    在看天翔哥的视频之后,他强调要把I2C协议好好研究一下,那么就对一些基本的通信手段是十分有帮助的..那么就来了解一下I2C总线协议的一些知识吧. I2C(Inter-Integrated Circui ...

  3. 在安卓下使用python连接蓝牙串口模块(HC-06)

    在安卓上安装Python: 请参考:https://github.com/kuri65536/python-for-android/blob/master/README.md下载程序文件需要访问 ht ...

  4. 目前电脑的硬件尺寸参数,计划弄个小一些的ATX机箱

    显卡:讯景R9 370x 尺寸:234×115×39mm 主板:技嘉GA-970A-DS3P 尺寸: 30.5X21.5 cm

  5. JavaScript 零散知识点1 (正则表达式+定时器+hover)

    1.clear:both清楚浮动影响//css中 2.正则表达式 search方法 :指明是否存在相应的匹配,如找到一个返回一个整数值,表明这个匹配距离字符串开始的偏移位置,如果没有找到匹配返回-1f ...

  6. MySQL 知识点

    文件格式: frm.MYI.MYD   分别是   MyISAM   表的表结构\索引\数据文件       一个库在一个目录下    不过在   MySQL   4.0   以上版本中,    你可 ...

  7. Google Map JavaScript API V3 实例大全

    Google Map JavaScript API V3 实例大全 基础知识 简单的例子 地理位置 语言 位置 坐标 简单的投影 事件 简单事件 关闭事件 多次添加事件 事件属性 控制 php禁用ui ...

  8. 读取tomcat下的文件夹路径

    背景:测试的为了每次部署时清缓存,将temp文件夹也删了,导致系统中有些excel导出功能用不了. 解决:新建一个监听文件,在系统启动时,判断temp文件夹是否存在,不存在就新建. temp文件夹的作 ...

  9. Sytem 表空间很大

    SYSTEM表空间使用率达到了99%, 经查出,是审计表AUD$占用绝大部分的空间. -- 占用表空间system对象大小排名 SELECT * MB FROM DBA_SEGMENTS WHERE ...

  10. IOS 高级开发 KVC(二)

    前一篇博客最后介绍了KVC 再json 转模型时遇到一些问题.今天接着来介绍KVC 的其他用法.其实我们在一开始的时候就一直再强调命名的重要性.命名规范是KVC 存活的基础.如果没有这个条件支撑,那么 ...