Python3之运算符的重载

#运算符重载
让自定义类生成的对象能够使用运算符进行操作

作用:

  • 让自定义类的实例像内建对象一样进行运算符操作
  • 让程序简洁易读
  • 对自定义对象将运算符赋予新的规则

####算数运算符的重载

方法名(双下划线显示不出来) 运算符和表达式 说明
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 MyList:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'MyList({})'.format(self.data)

    def __add__(self, rhs):
        return MyList(self.data + rhs.data)

    def __mul__(self, rhs):
        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 减法
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({})'.format(self.data)

    def __mul__(self, rhs):
        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  # 调用 __rmul__方法
print(L3)  # MyList([1, 2, 3, 1, 2, 3, 1, 2, 3])

L4 = L2 * 2  # 调用 __mul__方法
print(L4)  # MyList([4, 5, 6, 4, 5, 6])

####复合赋值算数运算符的重载
以 x += y为例,此运算符会优先调用x.iadd(y) 的方法,如果此方法不存在则会拆解为:x = x +y,然后调用x = x.add(y)方法,如果也不存在,则会触发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 求幂运算
class MyList:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'MyList({})'.format(self.data)

    def __add__(self, rhs):
        return MyList(self.data + rhs.data)
   
    def __iadd__(self, rhs):
        print('__iadd__被调用了')
        self.data += rhs.data
        return self

L1 = MyList([1, 2, 3])
L2 = MyList([4, 5, 6])

L2 += L1  # 调用 __iadd__方法
print(L2)  # MyList([1, 2, 3, 4, 5, 6])

####比较运算符的重载

方法名(双下划线显示不出来) 运算符和表达式 说明
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 不等于

注:返回的是布尔值(True或False)

def __eq__(self, rhs):
    return self.__data == rhs.__data

s1 = OrderSet([1, 2, 3, 4])
if s1 == OrderSet([3, 4, 5]):
    print('s1 == OrderSet([3, 4, 5])')
else:
    print('s1 != OrderSet([3, 4, 5])')  

以上只是一部分代码

####位运算符重载

方法名(双下划线显示不出来) 运算符和表达式 说明
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 右移
class OrderSet:
    def __init__(self, iterable=()):
        self.__data = iterable

    def __repr__(self):
        return 'OrderSet({})'.format(self.__data)

    def __and__(self, rhs):
        r = set(self.__data) & set(rhs.__data)
        return OrderSet(list(r))

    def __or__(self, rhs):
        r = set(self.__data) | set(rhs.__data)
        return OrderSet(list(r))

    def __xor__(self, rhs):
        r = set(self.__data) ^ set(rhs.__data)
        return OrderSet(list(r))

s1 = OrderSet([1, 2, 3, 4])
s2 = OrderSet([3, 4, 5])
print(s1 & s2)  # OrderSet([3, 4])
print(s1 | s2)  # OrderSet([1, 2, 3, 4, 5])
print(s1 ^ s2)  # OrderSet([1, 2, 5])

####反向位运算符重载

方法名(双下划线显示不出来) 运算符和表达式 说明
rand(self, lhs) lhs & self 位与
ror(self, lhs) lhs \ self(竖线) 位或
rxor(self, lhs) lhs ^ self 位异或
rlshift(self, lhs) lhs << self 左移
rrshift(self, lhs) lhs >> self 右移

####复合赋值位运算符重载

方法名(双下划线显示不出来) 运算符和表达式 说明
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 MyList:
    def __init__(self, iterable=()):
        self.data = list(iterable)

    def __repr__(self):
        return 'MyList({})'.format(self.data)

    def __neg__(self):
        G = [-x for x in self.data]
        return MyList(G)

L1 = MyList([1, -2, 3, -4, 5])
L2 = -L1
print(L2)  # MyList([-1, 2, -3, 4, -5])

####in / not in 运算符重载
格式:

def __contains__(self, e):
	语句块
def __contains__(self, item):
	return item in self.__data

s1 = OrderSet([1, 2, 3, 4])
if 2 in s1:
    print('2 in s1 为真')

####索引和切片运算符的重载方法
让自定义的类型的对象能够支持索引和切片的操作

方法名(双下划线显示不出来) 运算符和表达式 说明
getitem(self, i) x = self[i] 索引或切片取值
setitem(self, i, v) self[i] = v 设置索引或切片
delitem(self, i) del self[i] 删除索引或切片
class MyList:
    def __init__(self, iterable=()):
        self.__data = list(iterable)

    def __repr__(self):
        return 'MyList({})'.format(self.__data)

    def __getitem__(self, i):
        print('i的值是', i)  # i的值是 3
        return self.__data[i]

    def __setitem__(self, key, value):
        self.__data[key] = value

    def __delitem__(self, key):
        # del self.__data[key]
        self.__data.pop(key)

L1 = MyList([1, -2, 0, -4, 5])
x = L1[3]
print(x)  # 4
L1[3] = 2
print(L1)  # MyList([1, -2, 0, 2, 5])

del L1[2]
print(L1)  # MyList([1, -2, 2, 5])

print(L1[::2])  # i的值是 slice(None, None, 2)
                    # [1, 2]

slice构造函数:
作用:
用于创建一个slice对象,此对象用于切片操作的传值
格式:

slice(start=None, stop=None, step=None)

slice对象的实例属性
start 切片的起始值 默认为None
stop 切片的终止值 默认为None
step 切片的步长 默认为None

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

    def __repr__(self):
        return 'MyList({})'.format(self.__data)

    def __getitem__(self, i):
        print('i的值是', i)
        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('用户正在用字符串进行索引操作')
        return self.__data[i]

L1 = MyList([1, -2, 0, -4, 5])
print(L1[1:3:2])

结果:

i的值是 slice(1, 3, 2)
用户正在用切片取值:
起始值是: 1
终止值是: 3
步长值是: 2
[-2]

本节完

你可能感兴趣的:(python3)