什么是魔法函数?
在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解释器获得长度,性能非常高,而不是遍历对象去获得长度。