#运算符重载
让自定义类生成的对象能够使用运算符进行操作
作用:
####算数运算符的重载
方法名(双下划线显示不出来) | 运算符和表达式 | 说明 |
---|---|---|
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]
本节完