You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python自定义类作为右侧操作数(other)的运算符重载实现方法

解决Python自定义类作为右侧操作数时的运算符问题

这个问题我太熟了!当你的自定义类对象在运算符右侧(比如5 + MyObj)时失效,核心原因是Python的运算符查找规则:

当执行a + b时,Python会先尝试调用a.__add__(b)。如果a是内置类型(比如int),它的__add__方法不知道怎么处理你的自定义类,就会返回NotImplemented。这时候Python才会去尝试调用b.__radd__(a)——也就是反向加法方法,如果你的类没实现这个方法,就会直接报错。

解决方案:重写对应的反向运算符方法

针对每个你需要支持的运算符,除了重写正向方法(比如__add__),还要重写对应的反向方法(比如__radd__)。这样不管你的类在运算符左侧还是右侧,都能被正确处理。

代码示例:以加法为例

先看有问题的原始代码:

class MyNumber:
    def __init__(self, value):
        self.value = int(value)
    
    def __str__(self):
        return str(self.value)
    
    def __add__(self, other):
        if isinstance(other, int):
            return MyNumber(self.value + other)
        return NotImplemented

此时MyNumber(3) + 5能正常运行,但5 + MyNumber(3)会抛出TypeError。

修改后的代码(添加反向加法):

class MyNumber:
    def __init__(self, value):
        self.value = int(value)
    
    def __str__(self):
        return str(self.value)
    
    def __add__(self, other):
        if isinstance(other, int):
            return MyNumber(self.value + other)
        return NotImplemented
    
    def __radd__(self, other):
        # 对于加法这种符合交换律的运算,直接复用__add__的逻辑即可
        return self.__add__(other)
        # 或者更直观的写法:return self + other

现在5 + MyNumber(3)就能正常返回MyNumber(8)了!

非交换律运算符的处理(比如减法、除法)

像减法这种不满足交换律的运算,__rsub__需要调整运算顺序:

def __sub__(self, other):
    if isinstance(other, int):
        return MyNumber(self.value - other)
    return NotImplemented

def __rsub__(self, other):
    if isinstance(other, int):
        # 注意顺序:左侧的int减去当前对象的value
        return MyNumber(other - self.value)
    return NotImplemented

关键注意事项

  • 一定要返回NotImplemented而不是抛出异常:当你的方法不支持某个类型时,返回NotImplemented会让Python继续尝试调用对方的反向方法,保持运算符的兼容性。
  • 复用逻辑减少冗余:对于交换律运算符(加、乘),__rop__直接调用__op__即可,不用重复写运算逻辑。
  • 其他运算符同理:比如乘法对应__rmul__,除法对应__rtruediv__,都按照这个思路实现。

内容的提问来源于stack exchange,提问作者xzeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:38:04