在Python中使用反向运算符

9 投票
4 回答
8808 浏览
提问于 2025-04-16 04:25

我之前从来没有处理过反向运算符。刚学完这个知识,想试试,但不知道为什么不管用。这里是我的代码:

>>> class Subtract(object):
    def __init__(self, number):
        self.number = number
    def __rsub__(self, other):
        return self.number - other.number

    
>>> x = Subtract(5)
>>> y = Subtract(10)
>>> x - y         # FAILS!

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    x - y
TypeError: unsupported operand type(s) for -: 'Subtract' and 'Subtract'
>>> x.__rsub__(y) # WORKS!
-5

如果我把 __rsub__ 改成 __sub__,就能正常工作了。

我哪里出错了?这些反向运算符的作用是什么呢?

4 个回答

4

来自Python的数据模型,详细信息可以查看这个链接:http://docs.python.org/reference/datamodel.html

这些方法是用来实现一些基本的数学运算,比如加、减、乘、除、取余等操作。当你用不同类型的对象进行运算时,如果左边的对象不支持这个操作,就会调用这些方法。举个例子,如果你想计算表达式 x - y,而 y 是一个有 __rsub__() 方法的类的实例,那么如果 x.__sub__(y) 返回 NotImplemented,Python 就会调用 y.__rsub__(x) 来进行计算。

不过,有一点要注意:这两个对象不能是同一个类的实例。也就是说,即使你在上面的例子中定义了一个 __sub__ 方法并返回 NotImplemented,你仍然会遇到同样的错误。Python 会认为你的 Subtract 类无法从 "Subtract" 对象中进行减法,无论顺序如何。

但是,这样做是可以的:

class Sub1(object):
    number = 5
    def __sub__(self, other):
        return NotImplemented

class Sub2(object):
    number = 2
    def __rsub__(self, other):
        return other.number - self.number


a = Sub1()
b = Sub2()

print a - b
6

__rsub__() 这个方法只有在两个操作数类型不同时才会被调用;如果它们类型相同,就会假设如果没有 __sub__ 这个方法,那它们是不能相减的。

另外要注意的是,你的逻辑是反的;你返回的是 self - other,而不是 other - self。

6

这些方法的目的是为了让你可以做到这一点:

class MyNumber(object):
    def __init__(self, x):
        self.x = x

print 10 - MyNumber(9) # fails because 10.__sub__(MyNumber(9)) is unknown

class MyFixedNumber(MyNumber):
    def __rsub__(self, other):
        return MyNumber( other - self.x )

print 10 - MyFixedNumber(9) # MyFixedNumber(9).__rsub__(10) is defined

不过这种情况很少用到,通常你只会使用相同类型的东西,直接用 __sub__ 方法就可以了。

撰写回答