【问题标题】:Using reverse operators in Python在 Python 中使用反向运算符
【发布时间】:2011-04-15 09:19:51
【问题描述】:

我以前从未处理过反向运算符,所以请不要燃烧!刚完成对它们的了解,所以想尝试一下。但由于某种原因,它不起作用。这是代码:

>>> 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__,它可以工作。

我做错了什么?还有这些反向运算符的目的是什么?

【问题讨论】:

    标签: python operators


    【解决方案1】:

    __rsub__() 只会在操作数不同类型时被调用;当它们属于同一类型时,假定如果__sub__ 不存在,则它们不能被减去。

    还要注意你的逻辑在任何情况下都是相反的;你返回的是 self - other 而不是 other - self

    【讨论】:

    • 因为__rsub__是你定义的函数,你可以像调用其他函数一样调用它;它只是不会被自动调用来实现- 运算符。
    • @Randy:因为当你显式调用它时,它只是一个常规方法。为什么你会期望它不起作用? __rsub__ 的唯一特别之处在于,在某些情况下,Python 会将减法运算 &lt;something&gt; - &lt;something else&gt; 转换为对 __rsub__ 的调用 - 但如答案中所述,您的示例中不存在这些特定情况。跨度>
    【解决方案2】:

    这些方法的重点是允许这样做:

    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__

    【讨论】:

      【解决方案3】:

      来自http://docs.python.org/reference/datamodel.html 的 Python 数据模型:

      调用这些方法来实现 二元算术运算(+, -、*、/、%、divmod()、pow()、**、>、&、^、|) 与反射(交换)操作数。这些功能仅 如果左操作数没有调用 支持相应操作 并且操作数不同 类型。 [2] 例如,评估 表达式 x - y,其中 y 是 具有一个类的实例 __rsub__() 方法,如果 x.__sub__(y) 返回则调用 y.__rsub__(x) 未实现。

      但是 - 两个对象不能属于同一个类 - 这意味着,即使您在上面的示例中放置一个返回 NotImplemented 的 __sub__ 方法,您仍然会得到相同的错误:Python 只是假设您的 Subtract 类可以无论顺序如何,都不要从“减去”iobjects 中减去。

      但是,这是可行的:

      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
      

      【讨论】:

      • 似乎 reqrlt 不适用于反射 eqlt 运算符超载。知道为什么吗?
      • 嗯 - 我刚刚对那个特定问题的答案投了赞成票 - 所以我想你已经找到了。否则在这里回答:stackoverflow.com/questions/47577395/…
      • 没错!瓦卢!
      【解决方案4】:

      提供methods with reflected operands 是为了让您的类可以在左操作数是原始操作数或其他不受您控制的事物时实现运算符:

      这些函数仅在左操作数不支持相应操作且操作数类型不同时才会调用。

      既然都是同一类型,那就是懦弱的拒绝,你应该实现__sub__方法。

      【讨论】:

        猜你喜欢
        • 2018-07-08
        • 1970-01-01
        • 2013-03-29
        • 1970-01-01
        • 2018-12-18
        • 2016-11-20
        • 2015-02-01
        • 2016-09-09
        • 2022-11-24
        相关资源
        最近更新 更多