【发布时间】:2021-10-14 17:33:24
【问题描述】:
我正在尝试使用__getattr__ 函数一次重载多个运算符。在我的代码中,如果我调用foo.__add__(other),它会按预期工作,但是当我尝试foo + bar 时,它不会。这是一个最小的例子:
class Foo():
def add(self, other):
return 1 + other
def sub(self, other):
return 1 - other
def __getattr__(self, name):
stripped = name.strip('_')
if stripped in {'sub', 'add'}:
return getattr(self, stripped)
else:
return
if __name__=='__main__':
bar = Foo()
print(bar.__add__(1)) # works
print(bar + 1) # doesn't work
我意识到在这个例子中只定义 __add__ 和 __sub__ 会更容易,但在我的情况下这不是一个选项。
另外,作为一个小问题,如果我替换该行:
if stripped in {'sub', 'add'}:
与
if hasattr(self, name):
代码有效,但随后我的 iPython 内核崩溃了。为什么会发生这种情况,我该如何预防?
【问题讨论】:
-
我很确定,但目前无法证明,
bar.__add__(1)和bar + 1之间的差异是因为后一种行为直接调用了方法__add__()中的行为,实际上没有以通常的方式访问它。我认为这是解释器为 most 内置函数所做的事情——至少在 cpython 中,其他实现可能会有所不同。 -
“如果我替换该行......代码可以工作,但是我的 iPython 内核会崩溃” - 替换不会使任何工作。你一定误解了你所看到的。
-
另外,Python 会绕过正常的属性查找来进行此类操作,因此不可能实现
__getattr__实现您的目标。只需实现__add__和__sub__。 -
我也认为(但不能证明)像加法/减法这样的重要操作绕过了
__getattr__机制,所以你的__getattr__不会被bar + 1调用 -
我不想实现
__add__和__sub__的原因是我想为一大堆运营商做这件事,我想避免冗余代码。但我想这是要走的路……
标签: python