Python3 魔术方法总结
Python3 常用魔术方法列表:
| 魔术方法 | 描述 |
|---|---|
| __new__ | 创建类并返回这个类的实例 |
| __init__ | 可理解为“构造函数”,在对象初始化的时候调用,使用传入的参数初始化该实例 |
| __del__ | 可理解为“析构函数”,当一个对象进行垃圾回收时调用 |
| __metaclass__ | 定义当前类的元类 |
| __class__ | 查看对象所属的类 |
| __base__ | 获取当前类的直接父类 |
| __bases__ | 获取当前类的所有直接父类 |
| __str__ | 定义当前类的实例的文本显示内容 |
| __getattribute__ | 定义属性被访问时的行为 |
| __getattr__ | 定义试图访问一个不存在的属性时的行为 |
| __setattr__ | 定义对属性进行赋值和修改操作时的行为 |
| __delattr__ | 定义删除属性时的行为 |
| __copy__ | 定义对类的实例调用 copy.copy() 获得对象的一个浅拷贝时所产生的行为 |
| __deepcopy__ | 定义对类的实例调用 copy.deepcopy() 获得对象的一个深拷贝时所产生的行为 |
| __eq__ | 定义相等符号“==”的行为 |
| __ne__ | 定义不等符号“!=”的行为 |
| __lt__ | 定义小于符号“<”的行为 |
| __gt__ | 定义大于符号“>”的行为 |
| __le__ | 定义小于等于符号“<=”的行为 |
| __ge__ | 定义大于等于符号“>=”的行为 |
| __add__ | 实现操作符“+”表示的加法 |
| __sub__ | 实现操作符“-”表示的减法 |
| __mul__ | 实现操作符“*”表示的乘法 |
| __div__ | 实现操作符“/”表示的除法 |
| __mod__ | 实现操作符“%”表示的取模(求余数) |
| __pow__ | 实现操作符“**”表示的指数操作 |
| __and__ | 实现按位与操作 |
| __or__ | 实现按位或操作 |
| __xor__ | 实现按位异或操作 |
| __len__ | 用于自定义容器类型,表示容器的长度 |
| __getitem__ | 用于自定义容器类型,定义当某一项被访问时,使用 self[key] 所产生的行为 |
| __setitem__ | 用于自定义容器类型,定义执行 self[key]=value 时产生的行为 |
| __delitem__ | 用于自定义容器类型,定义一个项目被删除时的行为 |
| __iter__ | 用于自定义容器类型,一个容器迭代器 |
| __reversed__ | 用于自定义容器类型,定义当 reversed( ) 被调用时的行为 |
| __contains__ | 用于自定义容器类型,定义调用 in 和 not in 来测试成员是否存在的时候所产生的行为 |
| __missing__ | 用于自定义容器类型,定义在容器中找不到 key 时触发的行为 |
| __mro__ | 新式类可以直接通过__mro__属性获取类的 MRO,即类的方法解析顺序 |
1.1 __slots__ 用法解析
默认情况下 Python 用一个字典来保存对象的实例属性,它允许在运行时任意设置新属性。每次实例化时都会分配一个新的字典,当实例对象非常多时,会存在空间的浪费,因此就有了__slots__。
__slots__是一个元组,类的实例只能拥有__slots__中定义的变量,不能再增加新的变量。
- 定义类变量时,不允许跟
__slots__中的属性同名; - 定义了
__slots__的类,类变量对实例而言是只读的,不允许通过实例对象修改它们的值; - 定义了
__slots__的类,实例化时会拒绝创建__dict__和__weakref__属性,以节约内存空间; - 子类未声明
__slots__时,不会继承父类的__slots__,即子类实例可以随意赋值属性; - 子类声明
__slots__时,会继承父类的__slots__,即子类可以定义的属性包括自身+父类的__slots__; - 如果父类存在
__dict__属性,则子类将继承__dict__。此时,即使子类声明了__slots__属性,依然可以任意添加变量。
类的属性包括变量和函数。
1.2 __mro__ 方法说明
Python3 新式类的方法解析顺序 MRO 排序应用了 C3 算法。可以通过类的__mro__属性获取解析顺序,也可以通过简单的多继承代码和其对应的拓扑排序的抽象图来计算方法解析顺序:按照拓扑树的排序来找入度为零的类,多个类同时入度为零时,按从左到右,从根到叶的顺序排序。
class D(object):
pass
class E(object):
pass
class F(object):
pass
class C(D, F):
pass
class B(E, D):
pass
class A(B, C):
pass
if __name__ == '__main__':
print A.__mro__

所以方法解析顺序是:先找到点 A 只有它没有被别人指向,输出 A ;去掉 A 及其伸出的两条线,剩 B 和 C 点同时满足只指向别人,按照树的顺序从左到右,故先输出 B ;去掉线剩 E 和 C ,输出 E ;去线剩 C,输出C;去线剩 D 和 F ,输出 D ;去线只剩 F ,输出 F ;最后输出 object。
1.3 getattr、__getattr__ 与 __getattribute__
Object 类中定义了__getattribute__,但没有定义__getattr__。所以定义类时,如果需要,则应该显式定义__getattr__方法。
在获取对象属性时,__getattribute__()是一定会被调用的,无论属性存不存在,首先都会调用这个魔法方法。如果获取不存在的对象属性时,调用__getattribute__()找不到这个属性,就会再调用__getattr__()这个魔法方法(如果类中定义了),可以通过在这个方法里设置属性不存在时的默认值。
使用getattr()方法获取属性时,也是同样的调用关系。只不过在getattr()带第三个参数作为默认值时,如果存在__getattr__()方法,则默认值不起作用,返回的属性值是__getattr__()方法的返回值。

浙公网安备 33010602011771号