对我来说,唯一的区别是常规操作需要再实例化一次,并且结果由这个新实例保存。因此常规实现应该调用另一个。
但是:这些(就地)方法应该尝试就地执行操作(修改 self)并返回结果(可以是但不一定是 self)。如果未定义特定方法,或者该方法返回 NotImplemented,则增强赋值将回退到普通方法。
在这里,我明白标准方法与我的相反:
__iadd__
依赖于__add__
EDIT,因为__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.copy()
来避免这种情况。
某些类型不允许修改(例如,元组是不可变的)。因此他们不允许就地操作。
此外,就地操作对于编程新手甚至Python新手来说并不完全直观。这是该语言的一个很好的功能,但仅此而已。
总体而言,常规操作是“正常”操作形式。如果您正在编写一个新类并希望支持运算符,您可能会首先考虑常规运算符,然后再考虑就地运算符,或者根本不考虑。按照你的方式,如果只定义了常规,就地就行不通。
但有时性能确实是一个问题,到位可以实现更有效的实施。这就是为什么您可以定义就地操作,而不只是让它调用常规操作。
您误解了文档并混淆了操作员和方法。不是
__iadd__
调用 __add__
,而是 +=
运算符(或者更确切地说是处理它的解释器部分)调用它。该运算符首先尝试调用 __iadd__
,如果不起作用(因为 __iadd__
不存在或返回 NotImplemented
),则该运算符会尝试 __add__
。这就是文档的意思。
__iadd__
调用__add__
也是没有意义的,因为这会创建一个不需要的新对象。
当类型 实现 __iadd__
时,也可能实现
__add__
,并且很可能
__add__
在制作副本后确实调用
__iadd__
,就像您所做的那样。