item系列
__getitem__- 以字典形式访问属性的时候触发
__setitem__- 以字典形式设置属性的时候触发
__delitem__- 以字典形式删除属性的时候触发
| |
__str__和__repr__控制输出
__str__会在print()打印时候调用,如果类中没重写则会调用默认的打印值,如果自定义了则会调用自定义的__str__方法__repr__这个实在控制台的时候输出,若一个类中没定义__str__但是定义了__repr__方法,则会调用__repr__的返回值。
| |
__slots__属性
1.
__slots__是什么?是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味看所有实例只有一个数据属性)
2.引子:使用点来访问属性本质就是在访问类或者对象的dict属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用
__slots__?- 字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用
__slots__取代实例的dict当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在slots中定义的那些属性名。
- 字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用
注意事项:
__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再支持一些普通类特性了,比如多继承。大多数情况下,你应该只在那些经常被使用到的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象。 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。更多的是用来作为一个内存优化工具。
| |
描述符
定义
- 一个描述符是一个有“绑定行为”的对象属性(object attribute),它的访问控制会被描述器协议方法重写。
- 任何定义了
__get__,__set__或者__delete__任一方法的类称为描述符类,其实例对象便是一个描述符,这些方法称为描述符协议。 - 当对一个实例属性进行访问时,Python 会按
obj.__dict__→type(obj).__dict__→type(obj)的父类.__dict__顺序进行查找,如果查找到目标属性并发现是一个描述符,Python 会调用描述符协议来改变默认的控制行为。 - 描述符是
@property``@classmethod``@staticmethod和super的底层实现机制。
特性
- 同时定义了
__get__和__set__的描述符称为 数据描述符(data descriptor); - 仅定义了
__get__的称为 非数据描述符(non-data descriptor) 。 - 两者区别在于:如果
obj.__dict__中有与描述符同名的属性,若描述符是数据描述符,则优先调用描述符,若是非数据描述符,则优先使用obj.__dict__中属性。 - 描述符协议必须定义在类的层次上,否则无法被自动调用。
描述符协议
| |
| |
| |
描述符的应用
| |
描述符总结
- 描述符是可以实现大部分python类特性中的底层魔法,包括
@classmethod.@staticmethd.@property甚至是__slots__属性 - 描述符是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件。
元类
- 元类是类的类,是类的模板
- 元类是用来控制如何创建类的,正如类是创建对象的模板一样
- 元类的实例为类,正如类的实例为对象(
f1对象是Foo类的一个实例,Foo类是type类的一个实例) type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象