设为首页 收藏本站
查看: 1230|回复: 0

[经验分享] Python面向对象运算符重载

[复制链接]

尚未签到

发表于 2018-8-14 13:37:54 | 显示全部楼层 |阅读模式
  运算符重载的概念如下:

  •   运算符重载让类拦截常规的Python运算;
  •   类可重载所有Python表达式运算符;
  •   类也可重载打印、函数调用、属性点号运算等内置运算;
  •   重载是类实例的行为想内置类型;
  •   重载是通过提供特殊名称的类方法来实现的;
常见的运算符重载方法
方法重载调用__init__构造函数对象建立:X =>所有重载方法的名称前后都有两个下划线字符,以便把同类中定义的变量名区别开来。构造函数和表达式:__init__和__sub__


  •   >>>>
  •   ...   def __init__(self, start):
  •   ...     self.data = start
  •   ...   def __sub__(self, other):
  •   ...     return Number(self.data - other)
  •   ...
  •   >>> X = Number(5)
  •   >>> Y = X - 2
  •   >>> Y
  •   <__main__.Number object at 0x10224d550>
  •   >>> Y.data
  •   3
索引和分片: __getitem__和__setitem__
  基本索引


  •   >>>>
  •   ...     def __getitem__(self, item):
  •   ...         return item ** 2
  •   ...
  •   >>>
  •   >>> for i in range(5):
  •   ...     I = Index()
  •   ...     print(I, end=' ')
  •   ...
  •   0 1 4 9 16
  切片索引


  •   >>>>
  •   ...   data = [5, 6, 7, 8, 9]
  •   ...   def __getitem__(self, item):
  •   ...     print('getitem: ', item)
  •   ...     return self.data[item]
  •   ...   def __setitem__(self, key, value):
  •   ...     self.data[key] = value
  •   ...
  •   >>> X = Index()
  •   >>> print(X[1:4])
  •   getitem:  slice(1, 4, None)
  •   [6, 7, 8]
  •   >>> X[1:4] = (1, 1, 1)
  •   >>> print(X[1:4])
  •   getitem:  slice(1, 4, None)
  •   [1, 1, 1]
索引迭代:__getitem__
  如果重载了这个方法,for循环每次循环时都会调用类的getitem方法;


  •   >>>>
  •   ...     def __getitem__(self, item):
  •   ...         return self.data[item].upper()
  •   ...
  •   >>>
  •   >>> X = stepper()
  •   >>> X.data = 'ansheng'
  •   >>> for item in X:
  •   ...     print(item)
  •   ...
  •   A
  •   N
  •   S
  •   H
  •   E
  •   N
  •   G
迭代器对象:__iter__和__next__


  •   >>>>
  •   ...   def __init__(self, start, stop):
  •   ...         self.value = start - 1
  •   ...         self.stop = stop
  •   ...   def __iter__(self):
  •   ...         return self
  •   ...   def __next__(self):
  •   ...         if self.value == self.stop:
  •   ...             raise StopIteration
  •   ...         self.value += 1
  •   ...         return self.value ** 2
  •   ...
  •   >>> for i in Squares(1, 5):
  •   ...   print(i)
  •   ...
  •   1
  •   4
  •   9
  •   16
  •   25
成员关系:__contains__、__iter__和__getitem__

  •   class Iters:
  •   def __init__(self, value):
  •   self.data = value

  •   def __getitem__(self, item):
  •   print('get[%s]' % item, end='')
  •   return self.data[item]

  •   def __iter__(self):
  •   print('iter>==', end='')
  •   self.ix = 0
  •   return self

  •   def __next__(self):
  •   print('next:', end='')
  •   if self.ix == len(self.data): raise StopIteration
  •   item = self.data[self.ix]
  •   self.ix += 1
  •   return item

  •   def __contains__(self, item):
  •   print('contains: ', end=' ')
  •   return item in self.data


  •   X = Iters([1, 2, 3, 4, 5])
  •   print(3 in X)
  •   for i in X:
  •   print(i, end='|')

  •   print([i ** 2 for i in X])
  •   print(list(map(bin, X)))

  •   I = iter(X)
  •   while True:
  •   try:
  •   print(next(I), end=' @')
  •   except StopIteration as e:
  •   break
属性引用:__getattr__和__setattr__
  当通过未定义的属性名称和实例通过点号进行访问时,就会用属性名称作为字符串调用这个方法,但如果类使用了继承,并且在超类中可以找到这个属性,那么就不会触发。


  •   >>>>
  •   ...     def __getattr__(self, item):
  •   ...         if item == 'age':
  •   ...             return 40
  •   ...         else:
  •   ...             raise AttributeError(item)
  •   ...
  •   >>>
  •   >>> x = empty()
  •   >>> print(x.age)
  •   40
  •   >>> print(x.name)
  •   Traceback (most recent call last):
  •   File "<stdin>", line 1, in <module>
  •   File "<stdin>", line 6, in __getattr__
  •   AttributeError: name


  •   >>>>
  •   ...     def __setattr__(self, key, value):
  •   ...         if key == 'age':
  •   ...             self.__dict__[key] = value
  •   ...         else:
  •   ...             raise AttributeError(key + ' not allowed')
  •   ...
  •   >>>
  •   >>> x = accesscontrol()
  •   >>> x.age = 40
  •   >>> print(x.age)
  •   40
  •   >>> x.name = 'Hello'
  •   Traceback (most recent call last):
  •   File "<stdin>", line 1, in <module>
  •   File "<stdin>", line 6, in __setattr__
  •   AttributeError: name not allowed
__repr__和__str__会返回字符串表达式
  __repr__和__str__都是为了更友好的显示,具体来说,如果在终端下print(Class)则会调用__repr__,非终端下会调用__str__方法,且这两个方法只能返回字符串;

  •   class adder:
  •   def __init__(self, value=0):
  •   self.data = value

  •   def __add__(self, other):
  •   self.data += other

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

  •   def __str__(self):
  •   return 'N: %s' % self.data


  •   x = adder(2)
  •   x + 1
  •   print(x)
  •   print((str(x), repr(x)))
右侧加法和原处加法: __radd__和__iadd__
  只有当+右侧的对象是类实例,而左边对象不是类实例的时候,Python才会调用__radd__

  •   class Commuter:
  •   def __init__(self, val):
  •   self.val = val

  •   def __add__(self, other):
  •   print('add', self.val, other)
  •   return self.val + other

  •   def __radd__(self, other):
  •   print('radd', self.val, other)
  •   return other + self.val


  •   x = Commuter(88)
  •   y = Commuter(99)
  •   print(x + 1)
  •   print('')
  •   print(1 + y)
  •   print('')
  •   print(x + y)
  使用__iadd__进行原处加法

  •   class Number:
  •   def __init__(self, val):
  •   self.val = val

  •   def __iadd__(self, other):
  •   self.val += other
  •   return self


  •   x = Number(5)
  •   x += 1
  •   x += 1
  •   print(x.val)


  •   class Number:
  •   def __init__(self, val):
  •   self.val = val

  •   def __add__(self, other):
  •   return Number(self.val + other)


  •   x = Number(5)
  •   x += 1
  •   x += 1
  •   print(x.val)
Call表达式:__call__
  当调用类实例时执行__call__方法

  •   class Callee:
  •   def __call__(self, *args, **kwargs):
  •   print('Callee:', args, kwargs)


  •   C = Callee()
  •   C(1, 2, 3)
  •   C(1, 2, 3, x=1, y=2, z=3)


  •   class Prod:
  •   def __init__(self, value):
  •   self.value = value

  •   def __call__(self, other):
  •   return self.value * other


  •   x = Prod(3)
  •   print(x(3))
  •   print(x(4))
比较:__lt__,__gt__和其他方法
  类可以定义方法来捕获所有的6种比较运算符:<、>、<=、>=、==和!=

  •   class C:
  •   data = 'spam'

  •   def __gt__(self, other):
  •   return self.data > other

  •   def __lt__(self, other):
  •   return self.data < other

  •   x = C()
  •   print(x > 'han')
  •   print(x < 'han')
布尔值测试:bool和len

  •   class Truth:
  •   def __bool__(self):
  •   return True


  •   X = Truth()
  •   if X: print('yes')


  •   class Truth:
  •   def __bool__(self):
  •   return False

  •   X = Truth()
  •   print(bool(X))
  如果没有这个方法,Python退而求其次的求长度,因为一个非空对象看作是真:


  •   >>>>
  •   ...   def __len__(self): return 0
  •   ...
  •   >>> X = Truth()
  •   >>> if not X: print('no')
  •   ...
  •   no
  如果两个方法都有,__bool__会胜过__len__:


  •   >>>>
  •   ...   def __bool__(self): return True
  •   ...   def __len__(self): return 0
  •   ...
  •   >>> X = Truth()
  •   >>> bool(X)
  •   True
  如果两个方法都没有定义,对象毫无疑义的看作为真:


  •   >>>>
  •   ...
  •   >>> bool(Truth)
  •   True
对象解析函数:__del__
  每当实例产生时,就会调用init构造函数,每当实例空间被收回时,它的对立面__del__,也就是解析函数,就会自动执行;

  •   class Life:
  •   def __init__(self, name='unknown'):
  •   print('Hello, ', name)
  •   self.name = name

  •   def __del__(self):
  •   print('Goodbye', self.name)


  •   brian = Life('Brian')
  •   brian = 'loretta'

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-551703-1-1.html 上篇帖子: python标准库之collections 下篇帖子: python3学习之列表
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表