2017-05-20 78 views
1

numpy.ndarray我有具有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的方法形状,大小......直接在这个类的对象上。我也可以做像obj.__add__(1)这样的东西,它会把1加到obj._values。但是,如果我尝试obj + 1它会引发“不受支持的操作数类型”。我想获得obj + 1的相同行为obj.__add__(1)。如果不将__add__添加到Foo,这可能吗?

+1

不,这是不可能的。你必须实现'__add__'。 – DyZ

+0

Numpy 1.13rc2有一个mixin类,为你实现所有这些方法('numpy.lib.mixins.NDArrayOperatorsMixin') – Eric

回答

0

我可以看到你要在这里做什么,但它不会按照你认为应该的方式工作。这在Python中是一个非常明显的微妙之处。

你在想什么是你做了什么obj + 1 Python是实际调用obj.__add__(1)和,未能找到obj__add__属性它将通过落到其__getattr__

但是,这并不完全如此,算术运算符,它的实现实际上显着更复杂。在这种情况下,如果obj没有__add__方法,它将尝试调用右侧操作数的__radd__(用于“右添加”)方法以查看1是否知道如何使用左侧操作符进行添加。它不会让你得到一个异常。

还有其他一些细节,涉及类型插槽,我不会介入。

如果您希望自己的班级充当ndarray的代理人,那么您有几个选项。这实际上取决于你实际想要完成什么,你可能会考虑在另一个问题中提出。您可以直接在子类中直接执行子类ndarray并实现您的附加功能。

如果您不想要ndarray的子类,您可能还会考虑使用代理,例如wraptObjectProxy。这可能是也可能不是你想要的。它会使对象走动,说话,嘎嘎叫,甚至被命名为ndarray,尽管您仍然可以继承子类ObjectProxy以覆盖不需要代理的方法。

否则有繁琐的手动方法。

+0

谢谢!我真的不想子类化ndarray,因为它不是微不足道的,而且如果我没有定义'__setitem__',我就不会'obj [i,j] = 2'这个事实,我感到非常满意。我会考虑代理或手动添加一切。 – Max

+0

FWIW *一般* subndaring'ndarray'并不难,但不知道更多关于您的用例我不能说。 – Iguananaut