2

I have a custom class for which I want to implement the possibility of using the matrix multiplication @ operator.

In my class the __rmatmul__ method is defined and if I have e.g. an instance molecule the following works:

molecule.__rmatmul__( np.diag([1, 1, -1]))

But the following returns a ValueError:

np.diag([1, 1, -1]) @ molecule

I do not want to clump up this question with the code for the class definition. But If necessary I will provide it.

EDIT: I made a small test, with a minimal class to narrow the problem down:

class minimal:
     def __rmatmul__(self, other):
         return 1

     def __rmul__(self, other):
         return 2

test = minimal()

1 * test

returns 2 as expected.

np.zeros([3,3]) @ test

returns now a TypeError. Which is a bit inconsistent for me.

mcocdawc
  • 1,748
  • 1
  • 12
  • 21
  • If a value error is raised, that probably means that the Numpy implementation did not return a `NotImplemented` sentinel. Python checks the left-hand op *first*, unless the right-hand op type is a subclass of the left-hand. – Martijn Pieters Oct 14 '16 at 13:20
  • Try `np.diag([1, 1, -1]).__matmul__(molecule)` to verify. – Martijn Pieters Oct 14 '16 at 13:21
  • Yes, it gives a ``ValueError``. Is there a possibility to properly circumvent this? – mcocdawc Oct 14 '16 at 13:22
  • No, you'll have to file an issue with the numpy project to have that fixed. – Martijn Pieters Oct 14 '16 at 13:26
  • The [numpy source code](https://github.com/numpy/numpy/blob/c90d7c94fd2077d0beca48fa89a423da2b0bb663/numpy/core/src/multiarray/number.c#L101-L122) appears to imply that just implementing a `__rmatmul__` should be enough. Did you implement it on the *class* or on the instance? – Martijn Pieters Oct 14 '16 at 13:33
  • It is in the ``class`` definition. I made a test with a minimal class now, that is included in the updated question. – mcocdawc Oct 14 '16 at 13:34
  • I'd file this as a bug with the project. Having the mcve here is excellent. I certainly can reproduce this (`np.zeros([3, 3]).__matmul__(test)` raises a `TypeError`, it doesn't return `NotImplemented`), and `test.__rmatmul__(np.zeros([3, 3]))` returns `1` as expected. – Martijn Pieters Oct 14 '16 at 14:01
  • Thank you for your help! What does mcve mean? If you write an answer summarising, I will accept it. – mcocdawc Oct 14 '16 at 14:02
  • mcve == [mcve], something to reproduce the issue with concisely. – Martijn Pieters Oct 14 '16 at 14:06
  • 1
    Ah, looking at [Array and \_\_rmul\_\_ operator in Python Numpy](//stackoverflow.com/q/38229953) this appears to be a deliberate choice; only subclasses of `ndarray` are going to be supported. – Martijn Pieters Oct 14 '16 at 14:11
  • Yeah, this is, I am afraid, by design and the question is a duplicate (what applies to `__mul__` applies to `__matmul__` here too). – Martijn Pieters Oct 14 '16 at 14:12
  • It definitely is a duplicate. I just searched for ``__rmatmul__`` in the beginning. It also explains why I get once a ``TypeError`` and once a ``ValueError``. My minimal class is treated as scalar; my real class I am working on has ``__getitem__`` and similar methods implemented. I guess numpy tries to treat those instances as arrays. – mcocdawc Oct 14 '16 at 14:14

0 Answers0