Python运算符MRO:子类为右操作数时优先调用__rmul__而非__mul__
为什么子类继承父类时,
*运算符会先调用右操作数的__rmul__? 你的观察完全正确,这种反直觉的调用顺序是Python运算符分发机制中子类优先的特殊规则导致的,只在右操作数(RHS)是左操作数(LHS)的子类时触发。
核心逻辑
Python的运算符分发(比如*对应的__mul__/__rmul__)在处理继承关系时,会优先给子类机会处理跨类操作:
- 当计算
LHS * RHS时,如果type(RHS)是type(LHS)的子类(即你的例子中Vector继承自Matrix),Python会先尝试调用RHS.__rmul__(LHS),而非常规的先调用LHS.__mul__(RHS)。 - 只有当
RHS.__rmul__返回NotImplemented时,才会回退到调用LHS.__mul__(RHS)。 - 如果两者都返回
NotImplemented,就会抛出TypeError。
对应你的例子分析
执行matr * vec时:
- 因为
vec是Matrix的子类实例,Python优先调用vec.__rmul__(matr),输出Vector.__rmul__(⋯),该方法返回NotImplemented。 - 接着调用
matr.__mul__(vec),输出Matrix.__mul__(⋯),同样返回NotImplemented。 - 最终抛出
TypeError,提示不支持该操作数类型。
常规情况(无继承)
如果Vector不继承Matrix,Python会按你预期的顺序执行:先调用matr.__mul__(vec),返回NotImplemented后再调用vec.__rmul__(matr)。
这种设计是为了让子类可以自定义与父类的交互逻辑——比如如果Vector的__rmul__能处理和Matrix的乘法,就可以直接返回结果,不需要父类的方法介入。
内容的提问来源于stack exchange,提问作者geometrian
相关产品推荐
相关产品推荐

