课时42:魔法方法:算术运算
目录:
一、算术运算符
二、课时41课后习题及答案
现在来讲一个新名词:工厂函数。Python2.2以后,对类和类型进行了统一,做法就是将int()、float()、str()、list()、tuple()这些BIF转换为工厂函数:
>>> type(len) <class 'builtin_function_or_method'> >>> type(int) <class 'type'> >>> type(dir) <class 'builtin_function_or_method'> >>> type(list) <class 'type'>
看到没有,普通的BIF应该是<class 'builtin_function_or_method'>,而工厂函数则是<class 'type'>。大家有没有觉得<class 'type'>很眼熟,没错啦,如果定义一个类:
>>> class C: pass >>> type(C) <class 'type'>
它的类型也是type类型,也就是类对象,其实所谓的工厂函数,其实就是一个类对象。当你调用它们的时候,事实上就是创建一个相应的实例对象:
>>> a = int('123') >>> b = int('345') >>> a + b 468
现在你是不是豁然发现:原来对象是可以进行计算的!其实你早该发现这个问题了,Python中无处不对象,当在求a + b等于多少的时候,事实上Python就是在将两个对象进行相加操作。Python的魔法方法还提供了自定义对象的数值处理,通过下面这些魔法方法的重写,可以自定义任何对象间的算术运算。
******************
一、算术运算符
******************
表中列举了算术运算相关的魔法方法。
__add__(self, other) 定义加法的行为:+ __sub__(self, other) 定义减法的行为:- __mul__(self, other) 定义乘法的行为:* __truediv__(self, other) 定义真除法的行为:/ __floordiv__(self, other) 定义整数除法的行为:// __mod__(self, other) 定义取模算法的行为:% __divmod__(self, other) 定义当被 divmod() 调用时的行为 __pow__(self, other[, modulo]) 定义当被 power() 调用或 ** 运算时的行为 __lshift__(self, other) 定义按位左移位的行为:<< __rshift__(self, other) 定义按位右移位的行为:>> __and__(self, other) 定义按位与操作的行为:& __xor__(self, other) 定义按位异或操作的行为:^ __or__(self, other) 定义按位或操作的行为:|
举个例子,下面定义一个比较特立独行的类:
>>> class New_int(int): def __add__(self,other): return int.__sub__(self,other) def __sub__(self,other): return int.__add__(self,other) >>> a = New_int(3) >>> b = New_int(5) >>> a + b -2 >>> a - b 8
倘若你想自己写代码,不想通过调用Python默认的方案行不行?答案是肯定的,但是要格外小心。
>>> class Try_int(int): def __add__(self,other): return self + other def __sub__(self,other): return self - other >>> a = Try_int(1) >>> b = Try_int(3) >>> a + b Traceback (most recent call last): File "<pyshell#51>", line 1, in <module> a + b File "<pyshell#48>", line 3, in __add__ return self + other File "<pyshell#48>", line 3, in __add__ return self + other File "<pyshell#48>", line 3, in __add__ return self + other [Previous line repeated 990 more times] RecursionError: maximum recursion depth exceeded
为什么会陷入无限递归呢?问题出在这里:
def __add__(self,other): return self + other
当对象涉及加法操作时,自动调用魔法方法__add__(),但看看上边的魔法方法写的是什么?写的是return self + other,也就是返回对象本身加另外一个对象,这不就又自动触发调用__add__()方法了吗?这样就形成了无限递归。所以,要像下面这样写就不会触发无限递归了:
>>> class New_int(int): def __add__(self,other): return int(self) + int(other) def __sub__(self,other): return int(self) - int(other) >>> a = New_int(1) >>> b = New_int(3) >>> a + b 4
当对象进行相关的算术运算,自然而然就会自动触发对应的魔法方法。
通过对魔法方法的重写,你完全可以让Python根据你的意愿去执行:
>>> class int(int): def __add__(self,other): return int.__sub__(self,other) >>> a = int('5') >>> b = int('3') >>> a + b 2
当然,这样做在逻辑上是说不过去的...... emmmm
*******************************
二、课时41课后习题及答案
*******************************