贵阳市聚信天下网络科技有限公司
首页 | 联系方式 | 加入收藏 | 设为首页 | 手机站

产品目录

联系方式

联系人:业务部
电话: 00130-882723
邮箱:service@szshijibodd.com

当前位置:首页 >> 新闻中心 >> 正文

python之运算符重载

字号:
摘要: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]