【问题标题】:Overriding Commutative Operations For Same Class Operands in Python在 Python 中覆盖相同类操作数的交换操作
【发布时间】:2017-08-09 18:34:52
【问题描述】:

我正在尝试了解运算符覆盖如何适用于自定义类的两个操作数。

例如,假设我有以下内容:

class Adder:
    def __init__(self, value=1):
        self.data = value
    def __add__(self,other):
        print('using __add__()')
        return self.data + other
    def __radd__(self,other):
        print('using __radd__()')
        return other + self.data

我初始化了以下变量:

x = Adder(5)
y = Adder(4)

然后进行如下操作:

1 + x
using __radd__()
Out[108]: 6

x + 2
using __add__()
Out[109]: 7

上面的两个操作看起来很简单。如果我的自定义类的成员位于加法表达式中“+”的右侧,则使用 __radd__。如果它在左侧,则使用__add__。当一个操作数是Adder 类型而另一个是其他类型时,这适用于表达式。

但是,当我这样做时,我会得到以下结果:

x + y
using __add__()
using __radd__()
Out[110]: 9

如您所见,如果两个操作数都属于自定义类,则__add____radd__ 都会被调用。

我的问题是 Python 如何解决这种情况,它如何能够同时调用右手加法函数和左手加法函数。

【问题讨论】:

  • 我的理解是5+y应该调用y.__radd__(5)

标签: python oop operator-overloading overloading


【解决方案1】:

这是因为在您的方法中,您将数据添加到other。这本身就是 Adder 的一个实例。所以逻辑是:

  • 在 x 上致电 __add__
  • x.data(一个 int)添加到 y(一个 Adder 实例)
  • 啊,右手操作数是一个带有__radd__方法的实例,所以
  • 在 y 上致电 __radd__
  • 将 int 添加到 y.data(另一个 int)。

通常您会检查other 是否是您的类的实例,如果是,则添加other.data 而不仅仅是other

【讨论】:

    【解决方案2】:

    这是因为 __add____radd__ 方法的实现没有对 Adder 类的实例进行任何特殊处理。因此,每个__add__ 调用都会导致一个整数加Adder 实例 操作,由于右侧的Adder 实例进一步需要__radd__

    您可以通过以下方式解决此问题:

    def __add__(self, other):
        print('using __add__()')
        if isinstance(other, Adder):
            other = other.data
        return self.data + other
    
    def __radd__(self, other):
        print('using __radd__()')
        return self.__add__(other)
    

    【讨论】:

    • 这是有道理的。你是说当 Python 在右侧遇到 Adder 的实例而不是整数时,它会使用一些 wodoo 魔法使其成为整数?
    • @MadPhysicist 不会叫它magic。在第一次调用x.__add__(y) 之后,您希望如何解决5 + y
    • 这是我感到困惑的部分。你怎么能输入__add__ 并从它返回而不得到a + b 类型表达式的完整答案? __add__ 是否会以某种方式解析第一个操作数并确定它是x=5,然后将结果5 + y 反弹到__radd__ 方法?
    • @MadPhysicist 你读过 DanielRoseman 的回答吗?差不多解释了。 __add__ 调用 __radd__ 来解析不明确的 int + Adder 实例
    猜你喜欢
    • 2017-11-03
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2014-11-19
    • 2012-11-20
    相关资源
    最近更新 更多