__add__必须显式返回新对象,否则默认返回None导致加法失败;应返回同类型实例或NotImplemented以触发反向运算;__add__不可修改self,__iadd__才负责就地修改。

为什么__add__返回None会导致加法失败
直接写__add__但没写return,结果就是None。Python调用a + b时实际执行a.__add__(b),如果这个方法没返回值(即隐式返回None),整个表达式就变成None,后续再参与运算会立刻报TypeError: unsupported operand type(s)。
- 必须显式
return一个对象,通常是新实例或同类型对象 - 不要在
__add__里修改self——这是__iadd__干的事 - 如果右操作数类型不匹配,应返回
NotImplemented(不是NotImplementedError),让Python尝试b.__radd__(a)
如何正确实现__add__并支持不同类型右操作数
比如自定义Vector类,想让它既能和另一个Vector相加,也能和数字(如int)相加,就得判断other类型,并在不支持时返回NotImplemented。
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
<pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">def __add__(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 # 让Python尝试other.__radd__(self)
def __radd__(self, other):
# 支持 5 + vec 这种写法
if isinstance(other, (int, float)):
return Vector(self.x + other, self.y + other)
return NotImplemented</code></pre>注意:__radd__只在左操作数不支持时触发,所以<code>5 + vec能走通,但vec + 5走的是__add__。
__add__和__iadd__千万别混用
两者语义完全不同:__add__对应+(创建新对象),__iadd__对应+=(就地修改)。如果把__iadd__逻辑错放到__add__里,会导致a + b意外改变a的值,后续计算全乱。
立即学习“Python免费学习笔记(深入)”;
-
__add__:返回新实例,self不变 -
__iadd__:通常返回self(也可返回新对象,但违背直觉),且应修改内部状态 - 没实现
__iadd__时,a += b会退化为a = a + b,也就是调用__add__
常见报错和调试线索
遇到TypeError: unsupported operand type(s) for +,先检查三件事:
- 确认类里真有
__add__方法,且拼写准确(两个下划线前后各两个) - 看方法末尾有没有
return,以及返回值是不是None或错误类型 - 如果涉及自定义类相加,双方都要实现
__add__,或至少一方返回NotImplemented触发反向方法
最隐蔽的坑是返回了新对象但类型不对——比如__add__返回了tuple而不是自身实例,后续链式运算就会断掉。


















