一,运算符重载
如果通过定义一些特定的方法,就能针对自定义类型,让运算符有特定的作用。
比如,如果你在 Time 类中定义了一个名为add的方法,你就可以对 Time 对象使用 + 加号运算符。
>>> class Time:
... def __init__(self, hour=0, minute=0, second=0):
... self.hour = hour
... self.minute = minute
... self.second = second
... def __str__(self):
... return '%.2d:%.2d:%.2d' % (self.hour, self.minute, self.second)
... def time_to_int(time):
... minutes = time.hour * 60 + time.minute
... seconds = minutes * 60 + time.second
... return seconds
... def int_to_time(self, seconds): //这里是交互模式,不需要写入self,如果写到脚本里,要加self
... time = Time()
... minutes, time.second = divmod(seconds, 60)
... time.hour, time.minute = divmod(minutes, 60)
... return time
... def __add__(self, other):
... seconds = self.time_to_int() + other.time_to_int()
... return self.int_to_time(seconds) //这里是交互模式,不需要写入self,如果写到脚本里,要加self。
...
>>> start = Time(1, 20)
>>> duration = Time(2, 30)
>>> print(start + duration)
03:50:00
当你针对 Time 对象使用加号运算符的时候,Python 就会调用自定义的 add 方法。当用 print 输出结果的时候,Python 就会调用自定义的 str 方法。
针对用户自定义类型,让运算符有相应的行为,这就叫做运算符重载。Python 当中每一个运算符都有一个对应的方法,比如这里的add。
二,根据对象类型进行运算
1.我们可以把两个 Time 对象进行相加,但也许有时候需要把一个整数加到 Time 对象上面。
下面这一个版本的add方法就能够实现检查类型,然后调用add_time 方法或者是 increment 方法:
$ cat c.py
#!/bin/python
class Time:
def __init__(self, hour=0, minute=0, second=0):
self.hour = hour
self.minute = minute
self.second = second
def __str__(self):
return '%.2d:%.2d:%.2d' % (self.hour, self.minute, self.second)
def time_to_int(time):
minutes = time.hour * 60 + time.minute
seconds = minutes * 60 + time.second
return seconds
def int_to_time(self, seconds):
time = Time()
minutes, time.second = divmod(seconds, 60)
time.hour, time.minute = divmod(minutes, 60)
return time
def __add__(self, other):
if isinstance(other, Time):
return self.add_time(other)
else:
return self.increment(other)
def add_time(self, other):
seconds = self.time_to_int() + other.time_to_int()
return self.int_to_time(seconds)
def increment(self, seconds):
seconds += self.time_to_int()
return self.int_to_time(seconds)
内置函数isinstance 接收一个值和一个类的对象,如果该值是这个类的一个实例,就会返回真。
如果拿来相加的是一个 Time 对象,add就会调用 add_time 方法;其他情况下,程序会把参数当做一个数字,然后就调用 increment 方法。
这种运算就是根据对象进行的,因为在针对不同类型参数的时候,运算符会进行不同的计算。
下面的例子中,就展示了用不同类型变量来相加的效果:
01:43:57
2.其实,上面的这个加法运算不满足交换率,如果整数放到首位,就会得到如下所示的错误了:
>>> print(1437 + start)
Traceback (most recent call last):
File "c.py", line 35, in <module>
print(1437 + start)
TypeError: unsupported operand type(s) for +: 'int' and 'Time'
这里的问题就在于,Python 并没有让一个 Time 对象来加一个整数,而是去调用了整形的加法,然后把一个 Time 对象加到整数上面去,这就是用系统原本的加法,但这个加法不能处理 Time 对象。
针对这个问题,我们可以运用一个特殊的方法radd;这个方法的意思就是“右加”,即当一个 Time 对象出现在加号运算符右侧的时候,该方法就会被调用了。
在Time类定义里加入radd方法:
def __radd__(self, other):
return self.__add__(other)
然后把数字放到前面,再次打印就没有问题了:
01:43:57