用您班级的__mul__覆盖其他__rmul__ [英] Overriding other __rmul__ with your class's __mul__

查看:96
本文介绍了用您班级的__mul__覆盖其他__rmul__的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Python中,您的类的__rmul__方法是否可以覆盖另一个类的__mul__方法,而无需对另一个类进行更改?

In Python, is it possible for your class's __rmul__ method to override another class's __mul__ method, without making changes to the other class?

出现此问题是因为我正在为某种类型的线性运算符编写一个类,并且我希望它能够使用乘法语法将numpy数组相乘.这是一个说明问题的最小示例:

This question arises since I'm writing a class for a certain type of linear operator, and I want it to be able to multiply numpy arrays using the multiplication syntax. Here is a minimal example illustrating the issue:

import numpy as np    

class AbstractMatrix(object):
    def __init__(self):
        self.data = np.array([[1, 2],[3, 4]])

    def __mul__(self, other):
        return np.dot(self.data, other)

    def __rmul__(self, other):
        return np.dot(other, self.data)

左乘法工作正常:

In[11]: A = AbstractMatrix()
In[12]: B = np.array([[4, 5],[6, 7]])
In[13]: A*B
Out[13]: 
array([[16, 19],
       [36, 43]])

但是正确的乘法默认为np.ndarray的版本,它将数组拆分并逐元素执行乘法(这不是所希望的):

But right multiplication defaults to np.ndarray's version, which splits the array up and performs multiplication element-by-element (this not what is desired):

In[14]: B*A
Out[14]: 
array([[array([[ 4,  8],
       [12, 16]]),
        array([[ 5, 10],
       [15, 20]])],
       [array([[ 6, 12],
       [18, 24]]),
        array([[ 7, 14],
       [21, 28]])]], dtype=object)

在这种情况下,如何使它在原始(未拆分)数组上调用我自己类的__rmul__?

In this situation, how can I make it call my own class's __rmul__ on the original (unsplit) array?

欢迎回答有关numpy数组的特殊情况的答案,但我也对覆盖另一个无法修改的第三方类的方法的总体思路感兴趣.

Answers addressing the specific case of numpy arrays are welcome but I am also interested in the general idea of overriding methods of another third party class that cannot be modified.

推荐答案

使NumPy尊重您的__rmul__方法的最简单方法是设置

The easiest way to make NumPy respect your __rmul__ method is to set an __array_priority__:

class AbstractMatrix(object):
    def __init__(self):
        self.data = np.array([[1, 2],[3, 4]])

    def __mul__(self, other):
        return np.dot(self.data, other)

    def __rmul__(self, other):
        return np.dot(other, self.data)

    __array_priority__ = 10000

A = AbstractMatrix()
B = np.array([[4, 5],[6, 7]])

这像预期的那样工作.

>>> B*A
array([[19, 28],
       [27, 40]])

问题是NumPy不尊重 Pythons数值"数据模型.如果一个numpy数组是第一个参数,而numpy.ndarray.__mul__是不可能的,那么它将尝试如下操作:

The problem is that NumPy doesn't respect Pythons "Numeric" Data model. If a numpy array is the first argument and numpy.ndarray.__mul__ isn't possible then it tries something like:

result = np.empty(B.shape, dtype=object)
for idx, item in np.ndenumerate(B):
    result[idx] = A.__rmul__(item)

但是,如果第二个参数具有__array_priority__并且仅比第一个参数高,则它会确实使用:

However if the second argument has an __array_priority__ and it's higher than the one of the first argument only then it really uses:

A.__rmul__(B)


但是,自Python 3.5( PEP-465 )以来,可以利用的@( __matmul__ )运算符矩阵乘法:


However since Python 3.5 (PEP-465) there is the @ (__matmul__) operator that can utilize matrix multiplication:

>>> A = np.array([[1, 2],[3, 4]])
>>> B = np.array([[4, 5],[6, 7]])
>>> B @ A
array([[19, 28],
       [27, 40]])

这篇关于用您班级的__mul__覆盖其他__rmul__的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆