为何Python常规运算不基于其原地对应运算实现?
问题
我原本以为常规运算(比如a + b)和原地运算(比如a += b)的唯一区别就是常规运算多一次实例化,结果存在新实例里,所以常规运算的实现应该调用原地运算。但Python官方文档说:原地方法(比如__iadd__)会尝试修改self并返回结果,如果没定义这个方法或者返回NotImplemented,增强赋值会回退到常规方法(比如__add__)。这和我想的逻辑反过来了:是__iadd__兜底调用__add__。那为什么加法的默认实现是__add__而不是__iadd__?明明后者开销更低啊?
背景:这个问题来自我学习实现多项式类时的思考,我的代码实现如下:
class A: ... def __iadd__(self, other): "processing resulting in modification of attributes of self" return self def __add__(self, other): res = self.copy() # A.copy() being implemented as well res += other return res
回答
核心原因是语义优先级高于性能:
- 首先,加法(
a + b)的语义是「生成新结果,原对象保持不变」,这是最基础、最通用的加法逻辑,几乎所有支持加法的类型都要满足这个语义。而原地加法(a += b)是「修改原对象本身」的特殊场景,属于加法语义的衍生。Python把最通用的语义作为默认实现基础,符合语言设计的直觉。 - 其次,不是所有对象都支持原地修改。比如Python里的字符串、元组是不可变类型,它们根本没法实现
__iadd__,但必须支持常规加法。如果默认实现是__iadd__,这类不可变类型就没法满足基础加法需求了。 - 最后,你自己的实现方式其实是合理的——用
__iadd__实现具体加法逻辑,再让__add__通过复制+原地调用来复用代码,既保证语义正确,又避免重复代码。但这是具体类的实现策略,不是语言层面的默认规则。语言层面必须优先保证通用语义的覆盖,再考虑特殊场景的优化。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

