当我遇到__rsub__
方法时,我正在自学Python。虽然我可以找到explanation on the method in the official documentation:
调用这些方法来实现二进制算术运算(
+
,-
,*
,/
,//
,%
,反映了divmod()
,pow()
,**
,<<
,>>
,&
,^
,|
) (交换)操作数。仅当左操作数不支持相应操作且操作数具有不同类型时才调用这些函数。例如,要评估表达式x - y
,其中y
是具有__rsub__()
方法的类的实例,如果y.__rsub__(x)
返回{x.__sub__(y)
,则调用NotImplemented
{1}}。
我无法想象为什么这种方法是必要的以及它在现实中的使用方式。
请您给我一个典型的方法,该方法很有用吗?
答案 0 :(得分:4)
基本示例。你自己编写int
- 类:
class FooInt:
... other stuff elided ...
def __sub__(self, other):
if isinstance(other, FooInt):
return self.__class__(self.intvalue - other.intvalue)
elif isinstance(other, int):
return self.__class__(self.intvalue - other)
else:
return NotImplemented
现在你有代码:
FooInt(123) - 456
这很好用; Python在左侧看到FooInt
,看到它有__sub__
,并且调用FooInt.__sub__(FooInt(123), 456)
,它返回时没有错误,我们很好。
接下来我们看到:
123 - FooInt(456)
Python尝试调用int.__sub__(123, FooInt(456))
,但int
不知道如何处理FooInt
,并返回NotImplemented
;它不知道intvalue
具有可用于此目的的值。在这一点上,Python不能只调用FooInt.__sub__(FooInt(456), 123)
,因为它不能假设减法是可交换的(事实上,正如在大多数数值系统中,减法在这种情况下不是可交换的,你可以&# 39;只需交换操作员的右侧和左侧并获得正确的结果)。这就是__rsub__
存在的原因;它让你检查另一个类的处理操作的方法,同时告诉它两件事:
第二点也非常重要。在实施__xxx__
(左手操作员)时,您希望对您识别的类型保持非常保守。如果你不知道一个事实,你正在使用已知正确的处理程序的已知具体类型,你不应该尝试处理未知类型;另一种类型可能知道如何正确地进行操作,因此您返回NotImplemented
并让另一方处理它。当您实施__rxxx__
时,您是最后一次机会;另一个人不知道该怎么做,所以如果你有任何办法,你应该对自己接受的事情保持开放,并尽力做到最好。您可以在Implementing the arithmetic operations上的Python文档中看到这一点; __xxx__
操作检查具体类型(Fraction
,检查Fraction
,int
,float
和complex
),而__rxxx__
运算符会检查常规接口(numbers.Integral
,numbers.Rational
,numbers.Real
等。)
我已经掩盖了一个相对重要的观点:If the class on the right side is a subclass of the class on the left, it has its reflected __rxxx__
method called first;假设子类将有更多的信息来正确地确定要做什么,所以它给出了第一次执行操作的准备。