Python类默认不支持右侧算术运算,因__radd__等反向方法仅在左操作数__add__返回NotImplemented时才被调用;若抛异常或返回None,则直接报错。

Python 类默认不支持右侧算术运算(比如 1 + obj),除非你显式实现 __radd__ 等反向方法;否则会直接报 TypeError: unsupported operand type(s)。
为什么 __radd__ 不是自动调用的?
Python 的算术运算有明确的调用顺序:先尝试左操作数的 __add__,失败(返回 NotImplemented,不是 NotImplementedError!)后,才去查右操作数的 __radd__。如果左操作数抛出异常或返回其他值,__radd__ 根本不会被触发。
-
__add__必须显式返回NotImplemented(注意大小写),不能 return None 或 raise Exception - 内置类型如
int、str在不支持时也返回NotImplemented,所以你的类和它们混合运算才可能走到__radd__ - 如果左操作数是自定义类且没实现
__add__,Python 会直接报错,根本不会查右操作数
如何正确配对实现 __add__ 和 __radd__?
二者逻辑应保持一致,且 __radd__ 通常只处理「左操作数无法处理当前右操作数类型」的场景。常见做法是把计算逻辑提取到私有方法中,避免重复。
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
<pre class="brush:php;toolbar:false;">def _add_impl(self, other):
if isinstance(other, Vector):
return Vector(self.x + other.x, self.y + other.y)
elif isinstance(other, (int, float)):
return Vector(self.x + other, self.y + other)
return NotImplemented
def __add__(self, other):
result = self._add_impl(other)
return result if result is not NotImplemented else NotImplemented
def __radd__(self, other):
# int + Vector → 调用 Vector.__radd__
result = self._add_impl(other)
return result if result is not NotImplemented else NotImplemented
Python 编程规范与最佳实践。强制 PEP 8 代码风格、语法校验、单元测试执行,适用于代码编写、审查和重构。触发词:Python、代码规范、py_compile、单元测试。
立即学习“Python免费学习笔记(深入)”;
-
__radd__接收的是「左操作数」(即1 + v中的1),但方法体里它作为other传入逻辑函数 - 务必检查
isinstance(other, ...),别假设类型;否则__radd__可能被误用于不支持的类型 - 返回
NotImplemented表示“我也不支持”,让 Python 继续找下一个候选(比如父类方法),而不是抛错
哪些反向方法需要成对实现?
不是所有算术方法都有反向版本。常用且需配对的是:__radd__、__rsub__、__rmul__、__rtruediv__、__rpow__。而 __rfloordiv__、__rmod__、__rdivmod__ 等也存在,但使用频率低得多。
-
__rsub__和__rtruediv__特别容易写反:注意a - b对应a.__sub__(b),但b - a是a.__rsub__(b),即b - a == a.__rsub__(b),所以实现时是other - self.x,不是self.x - other - 没有
__req__或__rbool__—— 比较和布尔运算不走反向协议 -
__rmatmul__(@运算符)存在,但仅在需要支持矩阵乘法与标量混合时才需考虑
最容易被忽略的一点:反向方法只有在左侧对象明确放弃处理时才起作用;如果你的 __add__ 返回了 None 或抛了异常,__radd__ 就永远没机会运行。

















