【问题标题】:Confusing type of results of binary arithmetic operations involving Python builtin numeric types and Numpy types float64 and complex128涉及 Python 内置数字类型和 Numpy 类型 float64 和 complex128 的二进制算术运算结果的混淆类型
【发布时间】:2021-07-10 04:07:25
【问题描述】:

以乘法运算符mul为例,代码

import numpy as np

v = 1.0

a = float(v)
b = np.float64(v)

print(type(a*b), type(a.__mul__(b)))

a = complex(v)
b = np.complex128(v)
print(type(a*b), type(a.__mul__(b)))

产生以下输出

<class 'numpy.float64'> <class 'float'>
<class 'numpy.complex128'> <class 'complex'>

由于&lt;class 'float'&gt;.__mul__(&lt;class 'numpy.float64'&gt;)和&lt;class 'complex'&gt;.__mul__(&lt;class 'numpy.complex128'&gt;)实际上并不返回NotImplemented,根据Python documentation结果应该分别是&lt;class 'float'&gt;和&lt;class 'complex'&gt;。

为什么不是这样?似乎内置数字类型的二元算术运算符(+、-、*、/ 等)的行为与其对应的 __op__() 函数不同?

【问题讨论】:

  • 检查b.__rmul__(a)
  • b.__rmul__(a) 在这两种情况下都是正确的。问题是为什么a.__mul__(b) 在不 返回NotImplemented 时会被忽略。
  • numpy对象优先级较高,并控制'*'的形式
  • 这个优先级是什么?我似乎在 Python 文档中找不到任何关于此的内容。
  • 我不记得我在哪里读到过这个优先级,可能是在其他一些 SO 中。这是一些相关的问题,处理 0d 数组和 numpy 'scalar' 之间的区别,stackoverflow.com/questions/66169279/…

标签: python numpy


【解决方案1】:

我可能对priority 有误。有一个priority 值控制ndarray 及其子类如何交互,但对于Python 编号,它可能只是NotImplemented 或子类化的问题

https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types

Note If the right operand’s type is a subclass of the left operand’s type 
and that subclass provides a different implementation of the reflected 
method for the operation, this method will be called before the left 
operand’s non-reflected method. This behavior allows subclasses to 
override their ancestors’ operations.

用你的例子:

In [107]: a = 1.0; b = np.float64(1.0)
In [108]: type(a*b)
Out[108]: numpy.float64
In [109]: type(a.__mul__(b))
Out[109]: float
In [110]: type(b.__rmul__(a))
Out[110]: numpy.float64
In [111]: type(b).__mro__
Out[111]: 
(numpy.float64,
 numpy.floating,
 numpy.inexact,
 numpy.number,
 numpy.generic,
 float,
 object)

b 控制a*b,因为type(b) 是type(a) 的子类。使用b.__rmul__。

np.complex128 也是complex 的子类。

对于整数,not implemented 是因子

In [113]: c = 1; d = np.int64(1)
In [114]: type(c*d)
Out[114]: numpy.int64
In [115]: c.__mul__(d)
Out[115]: NotImplemented
In [116]: d.__rmul__(c)
Out[116]: 1
In [117]: type(_)
Out[117]: numpy.int64
In [118]: type(d).__mro__
Out[118]: 
(numpy.int64,
 numpy.signedinteger,
 numpy.integer,
 numpy.number,
 numpy.generic,
 object)

np.int64 不是int 的子类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-03
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    • 2015-11-07
    • 1970-01-01
    • 2021-03-15
    相关资源
    最近更新 更多