什么是魔法函数?
在Python中魔法函数以__开始以__结束
我们下面看看魔法函数有什么用
| 1 | class Company(object): | 
我们创建一个实例,然后使用for 循环遍历实例的属性employee。
有没有什么方法可以直接遍历实例,而不需要遍历属性employee就能获得属性值呢?
答案是魔法函数。
| 1 | class Company(object): | 
我们在类中增加魔法函数(魔法函数不是单属于一个类的单独方法)
现在我们可以直接对实例变量。
| 1 | company = Company(["tom", "bob", "jane"]) | 
实现原理是:当我们变量类实例的时候回去类里边查找是否存在__getitem__魔法函数,当存在时候,会逐个查找变量直至报错。也就是说当我们定义了函数__getitem__之后,对象就变成了可迭代对象。 
Python数据模型以及数据模型对Python的影响
魔法函数就是Python数据模型的一种理念。
Python中魔法函数会影响我们的Python语法的,我们在类中定义了魔法函数并不需要显示的调用。魔法函数是单独存在的,不是类继承与什么的父类得到的。我们在类中加入魔法函数之后会增加类的类型(上文说到的一些类型)。例如我们实现了__getitem__魔法函数之后就实现了序列类型,可以进行切片操作。
| 1 | company = Company(["tom", "bob", "jane"]) | 
如果没有实现__getitem__直接切片会报错的。
我们通过实现__getitem__使得能够切片,体现了魔法函数对Python的影响,我们大致可以认为Python一些模型的实现原理,例如切片正是实现了__getitem__。
例如我们想直接统计长度,在一个类的实例中。
| 1 | print(len(company)) | 
则会报没有len()方法,下面我们通过魔法函数实现。
| 1 | class Company(object): | 
这时会打印输出长度3.
Python魔法函数一览
非数学运算
字符串表示
| 1 | __repr__, __str__ | 
集合,序列相关
| 1 | __len__, __getitem__, __setitem__, __delitem__, __contains__ | 
迭代相关
| 1 | __iter__, __next__ | 
可调用
| 1 | __call__ | 
with上下文管理器
| 1 | __enter__, __exit__ | 
数值转换
| 1 | __abs__, __bool__, __int__, __float__, __hash__, __index__ | 
元类相关
| 1 | __new__, __init__ | 
属性相关
| 1 | __getattr__, __setattr__, __getattribute__, __setattribute__, __dir__ | 
属性描述符
| 1 | __get__, __set__, __delete__ | 
协程
| 1 | __await__, __aiter__, __anext__, __aenter__, __aexit__ | 
数学运算
一元运算符
| 1 | __neg__(-), __pos__(+), __abs__ | 
二元运算符
| 1 | __lt__(<), __le__(<=), __eq__(=), __ne__(!=), __gt__(>), __ge__(>=) | 
算术运算符
| 1 | __add__ + 、 __sub__ - 、 __mul__ * 、 __truediv__ / 、 __floordiv__ // 、 __mod__ % 、 __divmod__ divmod() 、 __pow__ ** 或 pow() 、 __round__ 、round() | 
反向算术运算符
| 1 | __radd__ 、 __rsub__ 、 __rmul__ 、 __rtruediv__ 、 __rfloordiv__ 、 __rmod__ 、 __rdivmod__ 、 __rpow__ | 
增量赋值算术运算符
| 1 | __iadd__ 、 __isub__ 、 __imul__ 、 __itruediv__ 、 __ifloordiv__ 、 __imod__ 、 __ipow__ | 
位运算符
| 1 | __invert__ ~ 、 __lshift__ << 、 __rshift__ >> 、 __and__ & 、 __or__ | 、 __xor__ ^ | 
反向未运算符
| 1 | __rlshift__ 、 __rrshift__ 、 __rand__ 、 __rxor__ 、 __ror__ | 
增量赋值位运算符
| 1 | __ilshift__ 、 __irshift__ 、 __iand__ 、 __ixor__ 、 __ior__ | 
我们看第一个__repr__和__str__,当我们打印输出一个对象的时候是默认调用str方法(对应魔法函数__str__)当我们未定义魔法函数只会打印出对象地址。__repr__是开发状态调用的(运行时)。魔法函数定义之后会隐式调用。
len函数的特殊性
当我们使用len()方法统计set,list,dict的长度的时候,会直接通过cpython解释器获得长度,性能非常高,而不是遍历对象去获得长度。
