这个问题与Overriding other __rmul__ with your class's __mul__中的问题很接近,但我认为这是一个更普遍的问题,只有数字数据。这也没有回答,我真的不想使用矩阵乘法@
进行此操作。因此,问题。
我确实有一个接受与标量和数值数组相乘的对象。像往常一样,左侧乘法工作正常,因为它使用的是myobj()
方法,但在右侧乘法中,NumPy使用广播规则并使用dtype=object
给出元素结果。
这也带来了无法检查数组大小是否兼容的副作用。
因此,问题是
有没有办法强制numpy数组查找其他对象的
__rmul__()
而不是广播和执行elementwise__mul__()
?
在我的特定情况下,对象是MIMO(多输入,多输出)传递函数矩阵(或者如果你愿意的话,还是滤波器系数矩阵),因此矩阵乘法在线性系统的加法和乘法方面具有特殊含义。因此,在每个条目中都有SISO系统。
import numpy as np
class myobj():
def __init__(self):
pass
def __mul__(self, other):
if isinstance(other, type(np.array([0.]))):
if other.size == 1:
print('Scalar multiplication')
else:
print('Multiplication of arrays')
def __rmul__(self, other):
if isinstance(other, type(np.array([0.]))):
if other.size == 1:
print('Scalar multiplication')
else:
print('Multiplication of arrays')
A = myobj()
a = np.array([[[1+1j]]]) # some generic scalar
B = np.random.rand(3, 3)
通过这些定义,以下命令显示了不需要的行为。
In [123]: A*a
Scalar multiplication
In [124]: a*A
Out[124]: array([[[None]]], dtype=object)
In [125]: B*A
Out[125]:
array([[None, None, None],
[None, None, None],
[None, None, None]], dtype=object)
In [126]: A*B
Multiplication of arrays
In [127]: 5 * A
In [128]: A.__rmul__(B) # This is the desired behavior for B*A
Multiplication of arrays
答案 0 :(得分:2)
默认情况下,NumPy假定未知对象(不是从ndarray继承)是标量,并且需要在任何NumPy数组的每个元素上“向量化”乘法。
要自己控制操作,您需要设置__array_priority__
(大多数向后兼容)或__array_ufunc__
(仅限NumPy 1.13+)。例如:
class myworkingobj(myobj):
__array_priority__ = 1000
A = myworkingobj()
B = np.random.rand(3, 3)
B * A # Multiplication of arrays
答案 1 :(得分:1)
我会尝试展示正在发生的事情。
In [494]: B=np.random.rand(3,3)
准系统课程:
In [497]: class myobj():
...: pass
...:
In [498]: B*myobj()
...
TypeError: unsupported operand type(s) for *: 'float' and 'myobj'
添加__mul__
In [500]: class myobj():
...: pass
...: def __mul__(self,other):
...: print('myobj mul')
...: return 12.3
...:
In [501]: B*myobj()
...
TypeError: unsupported operand type(s) for *: 'float' and 'myobj'
In [502]: myobj()*B
myobj mul
Out[502]: 12.3
添加rmul
:
In [515]: class myobj():
...: pass
...: def __mul__(self,other):
...: print('myobj mul',other)
...: return 12.3
...: def __rmul__(self,other):
...: print('myobj rmul',other)
...: return 4.32
...:
In [516]: B*myobj()
myobj rmul 0.792751549595306
myobj rmul 0.5668783619454384
myobj rmul 0.2196204913660168
myobj rmul 0.5474970289273348
myobj rmul 0.2079367474424587
myobj rmul 0.5374571198848628
myobj rmul 0.35748803226628456
myobj rmul 0.41306113085906715
myobj rmul 0.499598995529441
Out[516]:
array([[4.32, 4.32, 4.32],
[4.32, 4.32, 4.32],
[4.32, 4.32, 4.32]], dtype=object)
B*myobj()
以B
的形式提供给B.__mul__(myobj())
,myobj().__rmul__(i)
会为B
的每个元素执行myobj()*B
。
在myobj.__mul__(B)
转换为In [517]: myobj()*B
myobj mul [[ 0.79275155 0.56687836 0.21962049]
[ 0.54749703 0.20793675 0.53745712]
[ 0.35748803 0.41306113 0.499599 ]]
Out[517]: 12.3
In [518]: myobj().__rmul__(B)
myobj rmul [[ 0.79275155 0.56687836 0.21962049]
[ 0.54749703 0.20793675 0.53745712]
[ 0.35748803 0.41306113 0.499599 ]]
Out[518]: 4.32
:
myobj
您无法在B*myobj()
中执行任何操作来覆盖B.__mul__(myobj())
到/* /proc/net/route file:
Iface Destination Gateway Flags RefCnt Use Metric Mask
eno1 00000000 C900A8C0 0003 0 0 100 00000000 0 00
eno1 0000A8C0 00000000 0001 0 0 100 00FFFFFF 0 00
*/
const (
file = "/proc/net/route"
line = 1 // line containing the gateway addr. (first line: 0)
sep = "\t" // field separator
field = 2 // field containing hex gateway address (first field: 0)
)
func main() {
file, err := os.Open(file)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
// jump to line containing the agteway address
for i := 0; i < line; i++ {
scanner.Scan()
}
// get field containing gateway address
tokens := strings.Split(scanner.Text(), sep)
gatewayHex := "0x" + tokens[field]
// cast hex address to uint32
d, _ := strconv.ParseInt(gatewayHex, 0, 64)
d32 := uint32(d)
// make net.IP address from uint32
ipd32 := make(net.IP, 4)
binary.LittleEndian.PutUint32(ipd32, d32)
fmt.Printf("%T --> %[1]v\n", ipd32)
// format net.IP to dotted ipV4 string
ip := net.IP(ipd32).String()
fmt.Printf("%T --> %[1]v\n", ip)
// exit scanner
break
}
}
的翻译。如果需要更好地控制操作,请使用功能或方法。解释翻译很难。