Bootstrap

python之运算符重载

  •     运算符重载:

        什么是运算符重载
            让自定义的类生成的对象(实例)能够使用运算符进行操作
        作用:
            让自定义的实例像内建对象一样进行运算符操作
            让程序简洁易读
            对自定义对象将运算符赋予新的规则
        算术运算符的重载:
            方法名                  运算符和表达式      说明
            __add__(self,rhs)        self + rhs        加法
            __sub__(self,rhs)        self - rhs         减法
            __mul__(self,rhs)        self * rhs         乘法
            __truediv__(self,rhs)   self / rhs          除法
            __floordiv__(self,rhs)  self //rhs          地板除
            __mod__(self,rhs)       self % rhs       取模(求余)
            __pow__(self,rhs)       self **rhs         幂运算
            
        示例:
            

class Mynumber:
    def __init__(self,v):
        self.data = v
    def __repr__(self): #消除两边的尖括号
        return "Mynumber(%d)"%self.data

    def __add__(self,other):
        '''此方法用来制定self + other的规则'''

        v = self.data + other.data
        return Mynumber(v) #用v创建一个新的对象返回给调用者 

    def __sub__(self,other):
        '''此方法用来制定self - other的规则'''
        v = self.data - other.data
        return Mynumber(v)

n1 = Mynumber(100)
n2 = Mynumber(200)
# n3 = n1 + n2
n3 = n1+n2 # n3 = n1.__add__(n2)
print(n3)   #Mynumber(300)
n4 = n3 - n2 #等同于n4 = n3.__sub__(n2)
print("n4 = ",n4)

        rhs(right hand side) 右手边

        说明:
            运算符重载的方法的参数已经有了固定的含义,不建议改变原有的运算符的含义及参数的意义

        二元运算符的重载方法格式:
            def __xx__(self,other):
                语句块

    练习:
        实现两个自定义列表的相加
        class Mylist:
            def __init__(self,iterable=()):
                self.data = list(iterable)

        L1 = MyList([1,2,3])
        L2 = MyList([4,5,6])
        L3 = L1+L2
        print(L3)  #MyList([1,2,3,4,5,6])
        L4 = L2 + L3
        print(L4) #MyList([4,5,6,1,2,3])

        #试想能否实现以下操作
        L5 = L1 * 3
        print(L5)  #MyList([1,2,3,1,2,3,1,2,3])

class Mylist:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'Mylist(%s)' % self.data

    def __add__(self, lst):

        return Mylist(self.data + lst.data)

    def __mul__(self, rhs):
        # rhs为int类型,不能用rhs.data
        return Mylist(self.data * rhs)


L1 = Mylist([1, 2, 3])
L2 = Mylist([4, 5, 6])
L3 = L1 + L2
print(L3)  # Mylist([1,2,3,4,5,6])
L4 = L2 + L1
print(L4)  # Mylist([4,5,6,1,2,3])
L5 = L1 * 3
print(L5)  # Mylist([1,2,3,1,2,3,1,2,3])

    反向运算符的重载
        当运算符的左侧为内建类型时,右侧为自定义类型进行算术匀算符运算时会出现TypeError错误,因为无法修改内建类型的代码          实现运算符重载,此时需要使用反向运算符的重载
             反向算术运算符的重载:
            方法名                  运算符和表达式       说明
            __radd__(self,lhs)       lhs + self       加法
            __rsub__(self,lhs)       lhs - self       减法
            __rmul__(self,lhs)       lhs * self       乘法
            __rtruediv__(self,lhs)   lhs / self       除法
            __rfloordiv__(self,lhs)  lhs // self      地板除
            __rmod__(self,lhs)       lhs % self       取模(求余)
            __rpow__(self,lhs)       lhs ** self      幂运算
            
    示例:
        

class Mylist:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'Mylist(%s)' % self.data

    def __add__(self, lst):
        print('__add__被调用')
        return Mylist(self.data + lst.data)

    def __mul__(self, rhs):
        # rhs为int类型,不能用rhs.data
        print('__mul__被调用')
        return Mylist(self.data * rhs)

    def __rmul__(self, lhs):
        print("__rmul__被调用")
        return Mylist(self.data * lhs)


L1 = Mylist([1, 2, 3])
L2 = Mylist([4, 5, 6])
L3 = 3 * L1
print(L3)
L1 += L2
print(L1)
L2 *= 3
print(L2)


    复合赋值算术运算符的重载
        以复合赋值算术运算符 x += y为例,此运算符会优先调用x.__iadd__(y)方法,如果没有__iadd__方法时,则会将复合赋值算术运          算拆解为:x = x + y
        然后调用x = x.__add__(y)方法,如果再不存在__add__方法则会触发TypeError类型的错误异常

        复合赋值算术运算符的重载:
        方法名                  运算符和表达式      说明
        __iadd__(self,rhs)       self += rhs        加法
        __isub__(self,rhs)       self -= rhs         减法
        __imul__(self,rhs)       self *= rhs         乘法
        __itruediv__(self,rhs)   self /= rhs        除法
        __ifloordiv__(self,rhs)  self //=rhs        地板除
        __imod__(self,rhs)       self %= rhs     取模(求余)
        __ipow__(self,rhs)       self **=rhs       幂运算


    比较算术运算符的重载
        比较算术运算符的重载:
        方法名                  运算符和表达式      说明
        __lt__(self,rhs)       self < rhs        小于
        __le__(self,rhs)       self <= rhs       小于等于
        __gt__(self,rhs)       self > rhs        大于
        __ge__(self,rhs)       self >= rhs       大于等于
        __eq__(self,rhs)       self == rhs       等于
        __ne__(self,rhs)       self != rhs       不等于
        

    位运算符重载

            方法名              运算符和表达式        说明
        __and__(self,rhs)       self & rhs           位与
        __or__(self,rhs)        self | rhs              位或
        __xor__(self,rhs)       self ^ rhs             位异或
        __lshift__(self,rhs)    self <<rhs            左移
        __rshift__(self,rhs)    self >>rhs            右移

    反向位运算符重载

              方法名            运算符和表达式       说明
        __and__(self,lhs)       lhs & rhs             位与
        __or__(self,lhs)         lhs | rhs               位或
        __xor__(self,lhs)       lhs ^ rhs               位异或
        __lshift__(self,lhs)    lhs <<rhs              左移
        __rshift__(self,lhs)    lhs >>rhs              右移

    复合赋值位相关运算符重载
            方法名              运算符和表达式        说明
        __iand__(self,rhs)       self & rhs          位与
        __ior__(self,rhs)        self | rhs              位或
        __ixor__(self,rhs)       self ^ rhs            位异或
        __ilshift__(self,rhs)    self <<rhs           左移
        __irshift__(self,rhs)    self >>rhs           右移

        

    一元运算符的重载

     方法名              运算符和表达式        说明
     __neg__(self)         - self           负号
     __pos__(self)         + self           正号
     __invert__(self)      ~ self           取反

    语法:
        class 类名:
            def __xxx__(self):
                pass

    示例见:
        

class Mylist:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'Mylist(%s)' % self.data

    def __neg__(self):
        g = (-x for x in self.data)
        return Mylist(g)

    def __pos__(self):
        g = (abs(x) for x in self.data)
        return Mylist(g)


l1 = Mylist([1, -2, 3, -4, 5, -6])
l2 = - l1
print(l2)
l3 = +l1
print(l3)

in/not in 运算符重载
        格式:
            def __contains__(self,e):
                语句
            注: in / not in 返回布尔值 True / False
            当重载了__contains__后,in和not in运算符都可用
            not in 运算符的返回值与 in相反
        示例:       

class Mylist:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'Mylist(%s)' % self.data

    def __contains__(self, e):
        return True if e in self.data else False


l1 = Mylist([1, 2, 3, 4, -5, 6])
if 2 in l1:  # 等同于if l1.__contains__(4)
    print('2在l1内')
else:
    print('2不在l1内')
if -4 not in l1:  # 等同于if not l1.__contains__(4)
    print('-4不在l1内')
else:
    print('-4在l1内')


    索引和切片运算符重载方法:
        方法名                  运算符和表达式              说明
        __getitem__(self,i)     x = self(i)          索引/切片取值
        __setitem__(self,i,v)   self[i] = v          索引/切片赋值
        __delitem__(self,i)     del self[i]          del语句删除索引/切片


        作用:
            让自定义的类型的对象能够支持索引和切片操作
        示例: 

class Mylist:
    def __init__(self, iterable=()):
        self.__data = list(iterable)

    def __repr__(self):
        return 'Mylist(%s)' % self.__data

    def __getitem__(self, i):
        '索引取值,i绑定[]内的元素'
        print('i的值', i)
        return self.__data[i]  # 返回data绑定列表中的第i个元素

    def __setitem__(self, i, v):
        '''此方法可以让自定义的列表支持索引赋值操作'''
        print('__setitem__被调用,i = ', i, 'v = ', v)
        self.__data[i] = v

    def __delitem__(self, i):
        del self.__data[i]  # self.__data.pop(i)
        return self
        if type(i) is int:
            print('用户正在用索引取值')
        elif type(i) is slice:
            print('用户正在用切片取值')
            print('切片的起点是:', i.start)
            print('切片的终点是:', i.stop)
            print('切片的步长是:', i.step)
        elif type(i) is str:
            print('用户正在用字符串进行索引操作')
            # raise KeyError
        return self.__data[i]  # 返回data绑定的第i个元素


l1 = Mylist([1, 2, 3, 4, -5, 6])
print(l1[3])  # 4

l1[3] = 400
print(l1)  # Mylist([1, 2, 3, 400, -5, 6])

del l1[3]
print(l1)  # Mylist([1, 2, 3, -5, 6])

print(l1[::2])  # [1,3,6]


    slice构造函数
        作用:
            用于创建一个slice对象,此对于用于切片操作的传值
        格式:
            slice(start = None,stop = None ,step = None)
        slice对象的实例属性:
            start  切片的起始值,默认为None
            stop   切片的终止值,默认为None
            step   切片的步长,默认为None

 

特性属性@property
    实现其他语言所拥有的getter和setter功能

    作用:
        用来模拟一个属性
        通过@property装饰器,可以对模拟属性的赋值和取值加以控制
    示例:

class Student:
    def __init__(self, s):
        self.__score = s

    @property
    def score(self):
        print('getter被调用')
        return self.__score

    @score.setter
    def setScore(self, s):
        '''此方法用设置值加以限制以保证数据的准确性setter是用来数据的'''
        if 0 <= s <= 100:
            self.__score = s

    def getScore(self, s):
        '''getter只是用来获取数据'''
        return self.__score


s = Student(20)
# s.setScore(100)
score = s.score
print('成绩是:', score)


        

;