我有一个类,它有一个numpy.ndarray作为成员,并且通过重载__getitem__
和__getattr__
来表现类似于ndarray:
class Foo(object):
def __init__(values):
# numpy.ndarray
self._values = values
def __getitem__(self, key):
return self._values[key]
def __getattr__(self, name):
return getattr(self._values, name)
因此,我可以直接在此类的对象上使用numpy方法,如shape,size,....我也可以执行obj.__add__(1)
之类的操作,这会向obj._values
添加1。但是,如果我尝试obj + 1
,它会引发“不支持的操作数类型”。我希望obj + 1
与obj.__add__(1)
的行为相同。这可以在不将__add__
添加到Foo
的情况下实现吗?
答案 0 :(得分:0)
我可以看到你在这里尝试做什么,但它不会像你认为的那样工作。这是Python中非常明显的微妙之处。
你在想的是你所做的obj + 1
Python实际上正在调用obj.__add__(1)
而且,在__add__
找不到obj
属性它将会失败到__getattr__
。
但这并不完全是算术运算符的工作方式,其实现实际上要复杂得多。在这种情况下,如果obj
没有__add__
方法,则会尝试调用右侧操作数的__radd__
(用于“右侧添加”)方法来查看{{1}知道如何使用左手操作符添加。它不会让你得到例外。
还有其他涉及类型插槽的细微之处,我不会介入。
如果您希望自己的课程充当1
的代理人,那么您有几个选择。这实际上取决于你实际想要完成什么,你可以考虑在一个单独的问题中提出。您可能只能直接子类 ndarray
并在子类中实现其他功能。
如果您不想要ndarray
的子类,您也可以考虑使用代理,例如来自wrapt的ndarray
。这可能是也可能不是你想要的。虽然你仍然可以继承ObjectProxy
来覆盖你不想代理的方法,但它会使一个对象像走路,谈话,嘎嘎叫,甚至被称为ndarray
。
否则就会有繁琐的手动方法。