Python中算术运算符的重载链接

Python中算术运算符的重载链接,python,operator-overloading,Python,Operator Overloading,在我的类中,当使用诸如+、-等操作符时,我经常使用中的重载来定义它们的行为,方法是覆盖\uuuuuuuu add\uuuuuu、\uu sub\uuuuuu等方法 例如: class MyClass: def __add__(self, other): result = my_custom_adder(self, other) return self.__class__(result) 当链接这些被覆盖的操作符时,有没有办法定义行为 例如,一个复

在我的类中,当使用诸如
+
-
等操作符时,我经常使用中的重载来定义它们的行为,方法是覆盖
\uuuuuuuu add\uuuuuu
\uu sub\uuuuuu
等方法

例如:

class MyClass:    
    def __add__(self, other):
        result = my_custom_adder(self, other)
        return self.__class__(result)
当链接这些被覆盖的操作符时,有没有办法定义行为

例如,一个复杂类的三个元素
a+b+c
的添加可以通过同时考虑所有三个元素而不仅仅是顺序计算
(a+b)+c
来更有效地实现

当然,我可以介绍一个类方法:

class MyClass:    
    def __add__(self, other):
        return self.my_custom_adder(self, other)

    @classmethod
    def my_custom_adder(cls, *args):
        result = do_efficient_addition(*args)
        return cls(result)

然后,我可以调用
我的自定义加法器(a,b,c)
。但是这需要用户知道有这样一个方法,并显式地调用它,而不是仅仅使用
a+b+c

+
-
,等等。。。是二进制运算符

>>> tree=ast.parse('a+b+c')
>>> astpretty.pprint(tree)
Module(
    body=[
        Expr(
            lineno=1,
            col_offset=0,
            value=BinOp(
                lineno=1,
                col_offset=3,
                left=BinOp(
                    lineno=1,
                    col_offset=0,
                    left=Name(lineno=1, col_offset=0, id='a', ctx=Load()),
                    op=Add(),
                    right=Name(lineno=1, col_offset=2, id='b', ctx=Load()),
                ),
                op=Add(),
                right=Name(lineno=1, col_offset=4, id='c', ctx=Load()),
            ),
        ),
    ],
)
所以,不,没有办法覆盖那些操作符来得到你想要的


使用静态方法。

不,对于这样的钩子方法来说,没有任何东西可以知道它们是更大等式的一部分

您可以做的是生成一个中间结果对象,该对象收集对象,并且仅当您需要结果时才进行实际计算

例如,如果对象类似整数,并且实现了以便于转换,则中间值可以将计算推迟到:

class BaseIntValue(object):
    def __init__(self, value):
        self.value = value
    def __repr__(self):
        attrs = ', '.join([f"{k}={v!r}" for k, v in vars(self).items()])
        return f'{type(self).__name__}({attrs})'
    def __int__(self):
        return int(self.value)
    def __add__(self, other):
        if not isinstance(other, BaseIntValue):
            return NotImplemented
        return IntermediarySummedIntValue(self, other)

class IntermediarySummedIntValue(BaseIntValue):
    def __init__(self, *values):
        self.values = values
    def __int__(self):
        print("Expensive calculation taking place")
        return sum(map(int, self.values))
    def __add__(self, other):
        if not isinstance(other, BaseIntValue):
            return NotImplemented
        if isinstance(other, IntermediarySummedIntValue):
            values = self.values + other.values
        else:
            values = self.values + (other,)
        return IntermediarySummedIntValue(*values)
演示:


不可能<代码>+是一个二进制运算符(即它需要两个参数),对此您无能为力。谢谢Aran Fey。我的问题比您标记为重复的问题更一般,但答案仍然适用。这实际上是一个很好的技巧+1.
>>> BaseIntValue(42) + BaseIntValue(81) + BaseIntValue(314)
IntermediarySummedIntValue(values=(BaseIntValue(value=42), BaseIntValue(value=81), BaseIntValue(value=314)))
>>> int(BaseIntValue(42) + BaseIntValue(81) + BaseIntValue(314))
Expensive calculation taking place
437