1.例如:对于新的类来说,“+”操作符是未定义的,当我们在类中定义 __add__方法时,可重载“+”操作符,还有其他“-”、“/”、“*”等操作符,此处以__add__为例
class Vector():
def __init__(self, coords):
self.coords = coords
@property
def coords(self):
return self._coords
@coords.setter
def coords(self, value, d=3):
if not isinstance(value, list):
self._coords = [0] * d
else:
self._coords = value
def __add__(self, other):
if len(self.coords) != len(other):
raise ValueError('dimensions must be agree')
result = [0] * len(self.coords)
for j in range(len(self.coords)):
result[j] = self.coords[j] + other[j]
return result
def __str__(self):
return '<' + str(self._coords)[1: -1] + '>'
if __name__ == "__main__":
v = Vector([1, 2, 3])
w = v + [2, 3, 4]
print(w)
结果是:[3, 5, 7]
Vector接受一个列表,构造多维向量,该类用property创建了可管理的coords属性,使其可以接受任何形式的参数,当参数不是一个列表时,则提供一个所有坐标值为0的向量,在该类中有一个__add__方法,所以该类的实例可以实现“+”(以我们定义的方式,而不是一般的列表相加的方式)
2.python还有一些特殊的方法如__bool__, __iter__, __next__等方法,我们通过bool(foo), iter(foo), next(foo)等形式来调用这些方法。一些特殊方法由python提供了默认定义,如:对任何对象都支持if foo:即默认定义了__bool__方法,对于生成器器都默认定义了__next__方法,容器类实现了__len__和__getitem__方法,它可以自动提供一个默认迭代器,而一旦定义了迭代器,就自动提供了__contains__的默认功能。当已定义的类中没有实现特定的特殊方法,则依赖于该方法的语法将引发异常。
class Range():
def __init__(self, start, stop=None, step=1):
if step == 0:
raise ValueError('step can not be 0')
if stop is None:
start, stop = 0, start
self._start = start
self._step = step
self._stop = stop
def __len__(self):
return (self._stop - self._start + self._step - 1) // self._step
def __getitem__(self, item):
if item < 0:
item += len(self)
if not 0 <= item < len(self):
raise IndexError('index out of range')
return self._start + self._step * item
上面的Range类包含了__len__方法和__getitem__方法,则其支持迭代
练习题:通过实验对比2 in Range(1000000)和99999 in Range(1000000)的速度。请提供一种__contains__方法更有效的实现,以确定特定的值是否属于给定范围内,所提供方法的运行时间应独立于范围的大小。
首先我们来对比速度
from datetime import datetime
def get_time(a):
before = datetime.now()
print(a in Range(0, 1000000, 2))
after = datetime.now()
the_time = after - before
return the_time
print(get_time(2))
print(get_time(99999))
结果为:
True
0:00:00
False
0:00:00.877454
现在我们来设计一个__contains__方法
def __contains__(self, a):
b = (a - self._start) % self._step
c = (a - self._start) // self._step
if b == 0 and 0 <= c < len(self):
return True
return False
重复上面的get_time方法,结果为:
True
0:00:00
False
0:00:00