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