[英]How do I get __matmul__ of two different numpy.ndarray subclasses to return a particular subclass?
I have two np.ndarray
subclasses. 我有两个np.ndarray
子类。 Tuple @ Matrix
returns a Tuple
, but Matrix @ Tuple
returns a Matrix
. Tuple @ Matrix
返回一个Tuple
,但是Matrix @ Tuple
返回一个Matrix
。 How might I have it return a Tuple
instead? 我如何让它返回一个Tuple
呢?
import numpy as np
class Tuple(np.ndarray):
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
class Matrix(np.ndarray):
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
def scaling(x, y, z):
m = Matrix(np.identity(4))
m[0, 0] = x
m[1, 1] = y
m[2, 2] = z
return m
example: 例:
>>> Tuple([1,2,3,4]) @ scaling(2,2,2)
Tuple([2., 4., 6., 4.])
>>> scaling(2,2,2) @ Tuple([1,2,3,4])
Matrix([2., 4., 6., 4.]) # XXXX I'd like this to be a Tuple
PS: Matrix @ Matrix
should return Matrix
PS: Matrix @ Matrix
应该返回Matrix
You can overload the __matmul__
method to return a Tuple
- and if you want to be a Tuple
if any of the variables is a Tuple
and a Matrix
otherwise, I think this'll work: 您可以重载__matmul__
方法以返回一个Tuple
-并且如果您想成为一个Tuple
如果任何变量是Tuple
和Matrix
否则我认为这会起作用:
class Matrix(np.ndarray):
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
def __matmul__(m1, m2):
return (m2.T @ m1.T).T if isinstance(m2, Tuple) else np.matmul(m1, m2)
I made a mistake in copying from the np.matrix
example. 在从np.matrix
示例进行复制时,我犯了一个错误。
class Tuple(np.ndarray):
__array_priority__ = 10
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
class Matrix(np.ndarray):
__array_priority__ = 5.0
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
In [2]: def scaling(x, y, z):
...: ...: m = Matrix(np.identity(4))
...: ...: m[0, 0] = x
...: ...: m[1, 1] = y
...: ...: m[2, 2] = z
...: ...: return m
...:
In [3]: Tuple([1,2,3,4]) @ scaling(2,2,2)
Out[3]: Tuple([2., 4., 6., 4.])
In [4]: scaling(2,2,2) @ Tuple([1,2,3,4])
Out[4]: Tuple([2., 4., 6., 4.])
=== ===
Taking a clue from the np.matrix
definition: numpy.matrixlib.defmatrix.py 从np.matrix
定义中获取线索:numpy.matrixlib.defmatrix.py
Add a __array_priority__
attribute: 添加__array_priority__
属性:
In [382]: class Tuple(np.ndarray):
...: def __new__(cls, input_array, info=None):
...: __array_priority = 10
...: return np.asarray(input_array).view(cls)
...:
...: class Matrix(np.ndarray):
...: def __new__(cls, input_array, info=None):
...: __array_priority = 5
...: return np.asarray(input_array).view(cls)
...:
In [383]:
In [383]: def scaling(x, y, z):
...: m = Matrix(np.identity(4))
...: m[0, 0] = x
...: m[1, 1] = y
...: m[2, 2] = z
...: return m
...:
In [384]: Tuple([1,2,3,4]) @ scaling(2,2,2)
Out[384]: Tuple([2., 4., 6., 4.])
In [385]: scaling(2,2,2) @ Tuple([1,2,3,4])
Out[385]: Matrix([2., 4., 6., 4.])
One way of solving this is by implementing a custom __matmul__
in Matrix
and __rmatmul__
in Tuple
: 解决此问题的一种方法是在Matrix
实现自定义__matmul__
,在Tuple
实现__rmatmul__
:
import numpy as np
class Tuple(np.ndarray):
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
def __rmatmul__(self, other):
return super().__matmul__(other)
class Matrix(np.ndarray):
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
def __matmul__(self, other):
if not isinstance(other, Matrix):
return NotImplemented
return super().__matmul__(other)
def scaling(x, y, z):
m = Matrix(np.identity(4))
m[0, 0] = x
m[1, 1] = y
m[2, 2] = z
return m
scaling(2,2,2) @ scaling(2,2,2)
# Matrix([[4., 0., 0., 0.],
# [0., 4., 0., 0.],
# [0., 0., 4., 0.],
# [0., 0., 0., 1.]])
Tuple([1,2,3,4]) @ scaling(2,2,2)
# Tuple([2., 4., 6., 4.])
scaling(2,2,2) @ Tuple([1,2,3,4])
# Tuple([2., 4., 6., 4.])
Just overload __matmul__
of Matrix
class to return tuple instead 只需重载Matrix
类的__matmul__
即可返回元组
class Matrix(np.ndarray):
def __new__(cls, input_array, info=None):
return np.asarray(input_array).view(cls)
def __matmul__(self, other):
return other @ self
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.