运算符重载和python的特殊方法

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值