Python3操作符重载方法示例

基础知识

实际上,“运算符重载”只是意味着在类方法中拦截内置的操作……当类的实例出现在内置操作中,Python自动调用你的方法,并且你的方法的返回值变成了相应操作的结果。以下是对重载的关键概念的复习:

  1. 运算符重载让类拦截常规的Python运算。

  2. 类可重载所有Python表达式运算符

  3. 类可以重载打印、函数调用、属性点号运算等内置运算

  4. 重载使类实例的行为像内置类型。

  5. 重载是通过特殊名称的类方法来实现的。

换句话说,当类中提供了某个特殊名称的方法,在该类的实例出现在它们相关的表达式时,Python自动调用它们。正如我们已经学习过的,运算符重载方法并非必须的,并且通常也不是默认的;如果你没有编写或继承一个运算符重载方法,只是意味着你的类不会支持相应的操作。然而,当使用的时候,这些方法允许类模拟内置对象的接口,因此表现得更一致。

以下代码以Python3.6.1为例

操作符重载方法: 类(class)通过使用特殊名称的方法(len(self))来实现被特殊语法(len())的调用


   #coding=utf-8
   # specialfuns.py 操作符重载方法
   # 类(class)通过使用特殊名称的方法(__len__(self))来实现被特殊语法(len())的调用
   
   # 构造 与 析构 方法
   class demo1:
   
     # 构造方法, 对象实例化时调用
     def __init__(self):
       print("构造方法")
   
     # 析构方法, 对象被回收时调用
     def __del__(self):
       print("析构方法")
   
   
   # new
   class demo2(object):
     # __init__之前调用, 一般用于重写父类的__new__方法, 具体使用见 类 文章的 元类 代码部分(http://blog.csdn.net/rozol/article/details/69317339)
     def __new__(cls):
       print("new")
       return object.__new__(cls)
   
   
   # 算术运算
   class demo3:
     def __init__(self, num):
       self.data = num
     # +
     def __add__(self, other):
       return self.data + other.data
     # -
     def __sub__(self, other):
       return self.data - other.data
     # *
     def __mul__(self, other):
       return self.data * other.data
     # /
     def __truediv__(self, other):
       return self.data / other.data
     # //
     def __floordiv__(self, other):
       return self.data // other.data
     # %
     def __mod__(self, other):
       return self.data % other.data
     # divmod()
     def __divmod__(self, other):
       # 商(10/5),余数(10%5)
       return self.data / other.data, self.data % other.data
     # **
     def __pow__(self, other):
       return self.data ** other.data
     # <<
     def __lshift__(self, other):
       return self.data << other.data
     # >>
     def __rshift__(self, other):
       return self.data >> other.data
     # &
     def __and__(self, other):
       return self.data & other.data
     # ^
     def __xor__(self, other):
       return self.data ^ other.data
     # |
     def __or__(self, other):
       return self.data | other.data
   
   
   class none:
     def __init__(self, num):
       self.data = num
   # 反算术运算符(a+b, 若a不支持算术运算符,则寻找b的算术运算符)(注:位置变换, 在原始函数名前+r)
   class demo4:
     def __init__(self, num):
       self.data = num
     # +
     def __radd__(self, other):
       return other.data + self.data
     # -
     def __rsub__(self, other):
       return other.data - self.data
     # *
     def __rmul__(self, other):
       return other.data * self.data
     # /
     def __rtruediv__(self, other):
       return other.data / self.data
     # //
     def __rfloordiv__(self, other):
       return other.data // self.data
     # %
     def __rmod__(self, other):
       return other.data % self.data
     # divmod()
     def __rdivmod__(self, other):
       return other.data / self.data, other.data % self.data
     # **
     def __rpow__(self, other):
       return other.data ** self.data
     # <<
     def __rlshift__(self, other):
       return other.data << self.data
     # >>
     def __rrshift__(self, other):
       return other.data >> self.data
     # &
     def __rand__(self, other):
       return other.data & self.data
     # ^
     def __rxor__(self, other):
       return other.data ^ self.data
     # |
     def __ror__(self, other):
       return other.data | self.data
   
   
   # 增量赋值运算,(注:位置同原始函数,在原始函数名前+i)
   class demo5():
     def __init__(self, num):
       self.data = num
     # +=
     def __iadd__(self, other):
       return self.data + other
     # -=
     def __isub__(self, other):
       return self.data - other
     # *=
     def __imul__(self, other):
       return self.data * other
     # /=
     def __itruediv__(self, other):
       return self.data / other
     # //=
     def __ifloordiv__(self, other):
       return self.data // other
     # %=
     def __imod__(self, other):
       return self.data % other
     # **=
     def __ipow__(self, other):
       return self.data ** other
     # <<=
     def __ilshift__(self, other):
       return self.data << other
     # >>=
     def __irshift__(self, other):
       return self.data >> other
     # &=
     def __iand__(self, other):
       return self.data & other
     # ^=
     def __ixor__(self, other):
       return self.data ^ other
     # |=
     def __ior__(self, other):
       return self.data | other
   
   # 比较运算符
   class demo6:
     def __init__(self, num):
       self.data = num
     # <
     def __lt__(self, other):
       return self.data < other.data
     # <=
     def __le__(self, other):
       return self.data <= other.data
     # ==
     def __eq__(self, other):
       return self.data == other.data
     # !=
     def __ne__(self, other):
       return self.data != other.data
     # >
     def __gt__(self, other):
       return self.data > other.data
     # >=
     def __ge__(self, other):
       return self.data >= other.data
   
   
   # 一元操作符
   class demo7:
     def __init__(self, num):
       self.data = num
     # + 正号
     def __pos__(self):
       return +abs(self.data)
     # - 负号
     def __neg__(self):
       return -abs(self.data)
     # abs() 绝对值
     def __abs__(self):
       return abs(self.data)
     # ~ 按位取反
     def __invert__(self):
       return ~self.data
     # complex() 字符转数字
     def __complex__(self):
       return 1+2j
     # int() 转为整数
     def __int__(self):
       return 123
     # float() 转为浮点数
     def __float__(self):
       return 1.23
     # round() 近似值
     def __round__(self):
       return 1.123
   
   
   # 格式化
   class demo8:
     # print() 打印
     def __str__(self):
       return "This is the demo."
     # repr() 对象字符串表示
     def __repr__(self):
       return "This is a demo."
     # bytes() 对象字节字符串表现形式
     def __bytes__(self):
       return b"This is one demo."
     # format() 格式化
     def __format__(self, format_spec):
       return self.__str__()
   
   
   
   # 属性访问
   class demo9:
     # 获取(不存在)属性
     def __getattr__(self):
       print ("访问的属性不存在")
     # getattr() hasattr() 获取属性
     def __getattribute__(self, attr):
       print ("访问的属性是%s"%attr)
       return attr
     # setattr() 设置属性
     def __setattr__(self, attr, value):
       print ("设置 %s 属性值为 %s"%(attr, value))
     # delattr() 删除属性
     def __delattr__(self, attr):
       print ("删除 %s 属性"%attr)
   
   # ===================================================================
   # 描述器(类(test1)的实例出现在属主类(runtest)中,这些方法才会调用)(注:函数调用,这些方法不会被调用)
   class test1:
     def __init__(self, value = 1):
       self.value = value * 2
     def __set__(self, instance, value):
       print("set %s %s %s"%(self, instance, value))
       self.value = value * 2
     def __get__(self, instance, owner):
       print("get %s %s %s"%(self, instance, owner))
       return self.value
     def __delete__(self, instance):
       print("delete %s %s"%(self, instance))
       del self.value
   
   class test2:
     def __init__(self, value = 1):
       self.value = value + 0.3
     def __set__(self, instance, value):
       print("set %s %s %s"%(self, instance, value))
       instance.t1 = value + 0.3
     def __get__(self, instance, owner):
       print("get %s %s %s"%(self, instance, owner))
       return instance.t1
     def __delete__(self, instance):
       print("delete %s %s"%(self, instance))
       del self.value
   
   class runtest:
     t1 = test1()
     t2 = test2()
   
   # ---
   
   # 自定义property
   class property_my:
     def __init__(self, fget=None, fset=None, fdel=None):
       self.fget = fget
       self.fset = fset
       self.fdel = fdel
     # 对象被获取(self自身, instance调用该对象的对象(demo9), owner调用该对象的对象类对象(demo9))
     def __get__(self, instance, owner):
       print("get %s %s %s"%(self, instance, owner))
       return self.fget(instance)
     # 对象被设置属性时
     def __set__(self, instance, value):
       print("set %s %s %s"%(self, instance, value))
       self.fset(instance, value)
     # 对象被删除时
     def __delete__(self, instance):
       print("delete %s %s"%(self, instance))
       self.fdel(instance)
   
   class demo10:
     def __init__(self):
       self.num = None
     def setvalue(self, value):
       self.num = value
     def getvalue(self):
       return self.num
     def delete(self):
       del self.num
     x = property_my(getvalue, setvalue, delete)
   
   # ===================================================================
   
   # 自定义容器
   class lis:
     def __init__(self, *args):
       self.lists = args
       self.size = len(args)
       self.startindex = 0
       self.endindex = self.size
     # len() 容器元素数量
     def __len__(self):
       return self.size;
     # lis[1] 获取元素
     def __getitem__(self, key = 0):
       return self.lists[key]
     # lis[1] = value 设置元素
     def __setitem__(self, key, value):
       pass
     # del lis[1] 删除元素
     def __delitem__(self, key):
       pass
     # 返回迭代器
     def __iter__(self):
       return self
     # rversed() 反向迭代器
     def __reversed__(self):
       while self.endindex > 0:
         self.endindex -= 1
         yield self[self.endindex]
     # next() 迭代器下个元素
     def __next__(self):
       if self.startindex >= self.size:
         raise StopIteration # 控制迭代器结束
   
       elem = self.lists[self.startindex]
       self.startindex += 1
       return elem
   
     # in / not in
     def __contains__(self, item):
       for i in self.lists:
         if i == item:
           return True
       return False
   
   
   # yield 生成器(执行一次返回,下次继续执行后续代码返回)
   def yielddemo():
     num = 0
     while 1: # 1 == True; 0 == False
       if num >= 10:
         raise StopIteration
       num += 1
       yield num
   
   # 能接收数据的生成器
   def yielddemo_1():
     while 1:
       num = yield
       print(num)
   
   
   # with 自动上下文管理
   class withdemo:
     def __init__(self, value):
       self.value = value
     # 返回值为 as 之后的值
     def __enter__(self):
       return self.value
     # 执行完成,退出时的数据清理动作
     def __exit__(self, exc_type, exc_value, traceback):
       del self.value
   
   
   if __name__ == "__main__":
     # 构造与析构
     d1 = demo1()
     del d1
   
   
     # new
     d2 = demo2()
   
   
     # 算术运算符
     d3 = demo3(3)
     d3_1 = demo3(5)
     print(d3 + d3_1)
     print(d3 - d3_1)
     print(d3 * d3_1)
     print(d3 / d3_1)
     print(d3 // d3_1)
     print(d3 % d3_1)
     print(divmod(d3, d3_1))
     print(d3 ** d3_1)
     print(d3 << d3_1)
     print(d3 >> d3_1)
     print(d3 & d3_1)
     print(d3 ^ d3_1)
     print(d3 | d3_1)
   
   
     # 反运算符
     d4 = none(3)
     d4_1 = demo4(5)
     print(d4 + d4_1)
     print(d4 - d4_1)
     print(d4 * d4_1)
     print(d4 / d4_1)
     print(d4 // d4_1)
     print(d4 % d4_1)
     print(divmod(d4, d4_1))
     print(d4 ** d4_1)
     print(d4 << d4_1)
     print(d4 >> d4_1)
     print(d4 & d4_1)
     print(d4 ^ d4_1)
     print(d4 | d4_1)
   
   
     # 增量赋值运算(测试时注释其他代码)
     d5 = demo5(3)
     d5 <<= 5
     d5 >>= 5
     d5 &= 5
     d5 ^= 5
     d5 |= 5
     d5 += 5
     d5 -= 5
     d5 *= 5
     d5 /= 5
     d5 //= 5
     d5 %= 5
     d5 **= 5
     print(d5)
   
   
     # 比较运算符
     d6 = demo6(3)
     d6_1 = demo6(5)
     print(d6 < d6_1)
     print(d6 <= d6_1)
     print(d6 == d6_1)
     print(d6 != d6_1)
     print(d6 > d6_1)
     print(d6 >= d6_1)
   
   
     # 一元操作符(测试时注释其他代码)
     d7 = demo7(-5)
     num = +d7
     num = -d7
     num = abs(d7)
     num = ~d7
     print(num)
     print(complex(d7))
     print(int(d7))
     print(float(d7))
     print(round(d7))
   
   
     # 格式化
     d8 = demo8()
     print(d8)
     print(repr(d8))
     print(bytes(d8))
     print(format(d8, ""))
   
   
     # 属性访问
     d9 = demo9()
     setattr(d9, "a", 1) # => 设置 a 属性值为 1
     print(getattr(d9, "a")) # => a / 访问的属性是a
     print(hasattr(d9, "a")) # => True / 访问的属性是a
     delattr(d9, "a") # 删除 a 属性
     # ---
     d9.x = 100 # => 设置 x 属性值为 100
     print(d9.x) # => x / 访问的属性是x
     del d9.x # => 删除 x 属性
   
   
     # 描述器
     r = runtest()
     r.t1 = 100 # => <__main__.test1> <__main__.runtest> 100
     print(r.t1) # => 200 / <__main__.test1> <__main__.runtest> <class '__main__.runtest'>
     del r.t1 # => <__main__.test1> <__main__.runtest>
     r.t2 = 200 # => <__main__.test2> <__main__.runtest> 200 / <__main__.test1> <__main__.runtest> 200.3
     print(r.t2) # => 400.6 / <__main__.test2> <__main__.runtest> <class '__main__.runtest'> / <__main__.test1> <__main__.runtest> <class '__main__.runtest'>
     del r.t2 # <__main__.test2> <__main__.runtest>
     # ---
     # 自定义property
     d10 = demo10()
     d10.x = 100; # => <__main__.property_my> <__main__.demo10> 100
     print(d10.x) # => 100 / <__main__.property_my> <__main__.demo10> <class '__main__.demo10'>
     del d10.x # => <__main__.property_my> <__main__.demo10>
     d10.num = 200;
     print(d10.num) # => 200
     del d10.num
   
   
     # 自定义容器(迭代器Iterator)
     lis = lis(1,2,3,4,5,6)
     print(len(lis))
     print(lis[1])
     print(next(lis))
     print(next(lis))
     print(next(lis))
     for i in lis:
       print (i)
     for i in reversed(lis):
       print (i)
     print(3 in lis)
     print(7 in lis)
     print(3 not in lis)
     print(7 not in lis)
   
   
     # yield 生成器(可迭代对象Iterable)
     for i in yielddemo():
       print (i)
     # ---
     iters = iter(yielddemo())
     print(next(iters))
     print(next(iters))
   
     # --- 发送数据给生成器 ---
     iters = yielddemo_1()
     next(iters)
     iters.send(6) # 发送数据并执行
     iters.send(10)
   
   
     # with 自动上下文管理
     with withdemo("Less is more!") as s:
       print(s)
   
   

 

 

posted on 2021-06-16 22:25  BabyGo000  阅读(137)  评论(0)    收藏  举报