为什么常规操作不是基于其就地对应操作?

问题描述 投票:0回答:2

对我来说,唯一的区别是常规操作需要再实例化一次,并且结果由这个新实例保存。因此常规实现应该调用另一个。

但是这些(就地)方法应该尝试就地执行操作(修改 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
python operator-overloading in-place
2个回答
1
投票

就地操作可能会修改其操作数。在您给出的示例中,您使用

A.copy()
来避免这种情况。

某些类型不允许修改(例如,元组是不可变的)。因此他们不允许就地操作。

此外,就地操作对于编程新手甚至Python新手来说并不完全直观。这是该语言的一个很好的功能,但仅此而已。

总体而言,常规操作是“正常”操作形式。如果您正在编写一个新类并希望支持运算符,您可能会首先考虑常规运算符,然后再考虑就地运算符,或者根本不考虑。按照你的方式,如果只定义了常规,就地就行不通。

但有时性能确实是一个问题,到位可以实现更有效的实施。这就是为什么您可以定义就地操作,而不只是让它调用常规操作。


0
投票

您误解了文档并混淆了操作员和方法。不是

__iadd__
调用
__add__
,而是
+=
运算符(或者更确切地说是处理它的解释器部分)调用它。该运算符首先尝试调用
__iadd__
,如果不起作用(因为
__iadd__
不存在或返回
NotImplemented
),则该运算符会尝试
__add__
。这就是文档的意思。

__iadd__
调用
__add__
也是没有意义的,因为这会创建一个不需要的新对象。

当类型 实现 __iadd__

 时,也可能实现 
__add__
,并且很可能 
__add__
 在制作副本后确实调用 
__iadd__
,就像您所做的那样。

© www.soinside.com 2019 - 2024. All rights reserved.