问题 运算符在python中重载,运算符右侧的对象


我最近在python中了解了运算符重载,我想知道以下是否可行。

考虑下面的hypothetica /设法类。

class My_Num(object):
    def __init__(self, val):
        self.val = val
    def __add__(self, other_num):
        if isinstance(other_num, My_Num):
            return self.val + other_num.val
        else:
            return self.val + other_num

我知道上面写的方式,我可以做这样的事情

n1 = My_Num(1)
n2 = My_Num(2)
n3 = 3
print n1 + n2
print n1 + n3

这些将按预期工作。我也知道它目前写的方式我不能这样做

n1 = My_Num(1)
n2 = 2
print 2 + n1

有没有办法解决?我知道这个例子是设计的,但我有一个应用程序,如果我在运算符重载时,它非常有用,我定义运算符的类可以出现在运算符的右侧。这在python中可行吗?


7499
2018-05-07 23:40


起源



答案:


是。例如,有 __radd__。也, 没有了 对于 __le__()__ge__()等等,但正如Joel Cornett正确观察到的那样,如果你只定义 __lt__a > b 打电话给 __lt__ 的功能 b,提供了一种解决方法。

>>> class My_Num(object):
...     def __init__(self, val):
...         self.val = val
...     def __radd__(self, other_num):
...         if isinstance(other_num, My_Num):
...             return self.val + other_num.val
...         else:
...             return self.val + other_num
... 
>>> n1 = My_Num(1)
>>> n2 = 3
>>> 
>>> print n2 + n1
4
>>> print n1 + n2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'My_Num' and 'int'

请注意,至少在某些情况下,执行以下操作是合理的:

>>> class My_Num(object):
...     def __init__(self, val):
...         self.val = val
...     def __add__(self, other_num):
...         if isinstance(other_num, My_Num):
...             return self.val + other_num.val
...         else:
...             return self.val + other_num
...     __radd__ = __add__

10
2018-05-07 23:46



谢谢。是 RADD 唯一允许这样做的?我需要为我的应用程序重载的特定运算符是>>和<<运算符。我不幸运,我想为这些运营商做这件事吗? - martega
不。你点击了这个链接了吗?有 __rrshift__, 等等。 - senderle
通过控制为每个类定义哪些运算符,可以在有限的范围内进行比较。如果A和B只有 LT 例如,定义。 A <B和B> A将调用属于小端的方法。 - Joel Cornett
有没有办法改变一个opeartor的关联性?例如,我可以使>>运算符正确关联吗? - martega
@martega, 那, 一世 高度 怀疑。但我实际上并不知道。 - senderle


答案:


是。例如,有 __radd__。也, 没有了 对于 __le__()__ge__()等等,但正如Joel Cornett正确观察到的那样,如果你只定义 __lt__a > b 打电话给 __lt__ 的功能 b,提供了一种解决方法。

>>> class My_Num(object):
...     def __init__(self, val):
...         self.val = val
...     def __radd__(self, other_num):
...         if isinstance(other_num, My_Num):
...             return self.val + other_num.val
...         else:
...             return self.val + other_num
... 
>>> n1 = My_Num(1)
>>> n2 = 3
>>> 
>>> print n2 + n1
4
>>> print n1 + n2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'My_Num' and 'int'

请注意,至少在某些情况下,执行以下操作是合理的:

>>> class My_Num(object):
...     def __init__(self, val):
...         self.val = val
...     def __add__(self, other_num):
...         if isinstance(other_num, My_Num):
...             return self.val + other_num.val
...         else:
...             return self.val + other_num
...     __radd__ = __add__

10
2018-05-07 23:46



谢谢。是 RADD 唯一允许这样做的?我需要为我的应用程序重载的特定运算符是>>和<<运算符。我不幸运,我想为这些运营商做这件事吗? - martega
不。你点击了这个链接了吗?有 __rrshift__, 等等。 - senderle
通过控制为每个类定义哪些运算符,可以在有限的范围内进行比较。如果A和B只有 LT 例如,定义。 A <B和B> A将调用属于小端的方法。 - Joel Cornett
有没有办法改变一个opeartor的关联性?例如,我可以使>>运算符正确关联吗? - martega
@martega, 那, 一世 高度 怀疑。但我实际上并不知道。 - senderle


你必须超载 __radd__ 方法(右侧添加)。你的功能看起来和你的功能差不多 __add__ 方法,例如:

def __radd__(self, other):
     return self.val + other.val

1
2018-05-07 23:50