Bootstrap

Python 运算符重载

常见的运算符重载方法

在类中,对内置对象(例如,整数和列表)所能做的事,几乎都有相应的特殊名称的重载方法。下表列出其中一些最常用的重载方法。参见http://blog.csdn.net/gavin_john/article/details/50717695

方法重载调用
__init__构造函数 对象建立:X = Class(args)
__del__析构函数X对象收回
__add__运算符+如果没有_iadd_,X+Y,X+=Y
__or__运算符|(位OR)如果没有_ior_,X|Y, X|=Y
__repr__,__str__打印、转换print(X)repr(X),str(X)
__call__函数调用X(*args,**kargs)
__getattr__点号运算X.undefined
__setattr__属性赋值语句X.any = value
__delattr__属性删除del X.any
__getattribute__属性获取X.any
__getitem__索引运算X[key],X[i:j],没__iter__时的for循环和其他迭代器
__setitem__索引赋值语句X[key] = value,X[i:j] = sequence
__delitem__索引和分片删除del X[key],del X[i:j]
__len__长度len(X),如果没有__bool__,真值测试
__bool__布尔测试bool(X),真测试
__lt__,__gt__,特定的比较X < Y,X > Y
__le__,__ge__,X<=Y,X >= Y
__eq__,__ne__X == Y,X != Y
__radd__右侧加法Other+X
__iadd__实地(增强的)加法X += Y (or else __add__)
iter,next迭代环境I = iter(X),next(I)
__contains__成员关系测试item in X (任何可迭代的)
__index__整数值hex(X),bin(X),oct(X),O[X],O[X:]
__enter__,__exit__环境管理器with obj as var:
__get__,__set__描述符属性X.attr,X.attr = value,del X.attr
__new__创建__init__之前创建对象

对于二元运算符, 有一个invoke的顺序表, 以__eq__为例 参见http://stackoverflow.com/questions/3588776/how-is-eq-handled-in-python-and-in-what-order
总结起来就是
左结合优先, 然后右结合, 然后其他

对于修改自己的二元操作, 比如 &=,先__iand____and__
在找不到__ixx__的情况下调用 __xx__

综合起来, 在尝试完了左边的运算符后, 才能尝试右边的运算符
实例如下

In [0]: class A:
   ...:     def __init__(self):
   ...:         self.a =1
   ...:     def __add__(self, b):
   ...:         print('A add')
   ...:

In [1]: class B:
   ...:     def __init__(self):
   ...:         self.a =1
   ...:     def __iadd__(self, a):
   ...:         print('B iadd')
   ...:
In [2]: a = A()

In [3]: b =B()

In [4]: a += b
A add

重载二元自操作运算符

例如

__iand__ &= 
__ior__  |=
__ixor__ ^=
__isub__ -= 

#etc.
需要
1. self = 新实例
2. return self

例如:

Class OrderedSetAdapter():
    # ...
    def __ior__(self, other):
        self = OrderedSetAdapter(self.__or__(other))
        return self

更新操作

只有二元自操作运算符 __ixx__ 才能赋值self 实例 (self = xxxx)
其余方法更新实例, 只能用方法 clear + update, 创建新实例并直接赋值给self, 会在此方法结束后
失效!!

举个栗子

    class OrderedSet:
        # ...
        def intersection_update(self, *others):
            res = self.intersection(*others)
            self.clear()
            self.update(res)

        def __iand__(self, other):
            self = self.__and__(other)
            return self
;