9

通常,dtype当它等同于本机类型时,它是隐藏的:

>>> import numpy as np
>>> np.arange(5)
array([0, 1, 2, 3, 4])
>>> np.arange(5).dtype
dtype('int32')

>>> np.arange(5) + 3
array([3, 4, 5, 6, 7])

但不知何故,这不适用于地板除法或模数:

>>> np.arange(5) // 3
array([0, 0, 0, 1, 1], dtype=int32)
>>> np.arange(5) % 3
array([0, 1, 2, 0, 1], dtype=int32)

为什么有区别?

Python 3.5.4、NumPy 1.13.1、Windows 64 位

4

2 回答 2

5

您实际上在这里有多个不同的 32 位整数 dtype。这可能是一个错误。

NumPy 已经(不小心?)创建了多个不同的有符号 32 位整数类型,可能对应于 Cintlong. 它们都显示为numpy.int32,但它们实际上是不同的对象。在 C 级别,我相信类型对象是PyIntArrType_Typeand PyLongArrType_Type在这里生成。

dtype 对象具有type对应于该 dtype 标量的类型对象的属性。NumPy在决定是否在数组中打印信息时检查的是这个type属性:dtyperepr

_typelessdata = [int_, float_, complex_]
if issubclass(intc, int):
    _typelessdata.append(intc)


if issubclass(longlong, int):
    _typelessdata.append(longlong)

...

def array_repr(arr, max_line_width=None, precision=None, suppress_small=None):
    ...
    skipdtype = (arr.dtype.type in _typelessdata) and arr.size > 0

    if skipdtype:
        return "%s(%s)" % (class_name, lst)
    else:
        ...
        return "%s(%s,%sdtype=%s)" % (class_name, lst, lf, typename)

numpy.arange(5)numpy.arange(5) + 3,.dtype.typenumpy.int_; _ onnumpy.arange(5) // 3numpy.arange(5) % 3,.dtype.type是另一种 32 位有符号整数类型。

至于为什么+//有不同的输出dtypes,他们使用不同的类型解析例程。这是一个 for //是一个 for +//的类型解析寻找一个 ufunc 内部循环,该循环采用输入可以安全地转换为的类型,而+的类型解析将 NumPy 类型提升应用于参数并选择与结果类型匹配的循环。

于 2017-09-18T19:22:57.860 回答
2

它归结为 的差异,dtype从 中可以看出view

In [186]: x = np.arange(10)
In [187]: y = x // 3
In [188]: x
Out[188]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [189]: y
Out[189]: array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3], dtype=int32)
In [190]: x.view(y.dtype)
Out[190]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)
In [191]: y.view(x.dtype)
Out[191]: array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3])

虽然dtype descr相同,但也有不同的属性。但是哪个?

In [192]: x.dtype.descr
Out[192]: [('', '<i4')]
In [193]: y.dtype.descr
Out[193]: [('', '<i4')]

In [204]: x.dtype.type
Out[204]: numpy.int32
In [205]: y.dtype.type
Out[205]: numpy.int32
In [207]: dtx.type is dty.type
Out[207]: False

In [243]: np.core.numeric._typelessdata
Out[243]: [numpy.int32, numpy.float64, numpy.complex128]
In [245]: x.dtype.type in np.core.numeric._typelessdata
Out[245]: True
In [246]: y.dtype.type in np.core.numeric._typelessdata
Out[246]: False

所以ysdtype.type从所有外观上看都与xs 相同,但它是一个不同的对象,具有不同的id:

In [261]: id(np.int32)
Out[261]: 3045777728
In [262]: id(x.dtype.type)
Out[262]: 3045777728
In [263]: id(y.dtype.type)
Out[263]: 3045777952
In [282]: id(np.intc)
Out[282]: 3045777952

将此额外添加type到列表中,y不再显示 dtype:

In [267]: np.core.numeric._typelessdata.append(y.dtype.type)
In [269]: y
Out[269]: array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3])

(and )y.dtype.type也是如此,而(and )也是如此。np.intcnp.intpx.dtype.typenp.int32np.int_

因此,要创建一个显示 dtype 的数组,请使用np.intc.

In [23]: np.arange(10,dtype=np.int_)
Out[23]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [24]: np.arange(10,dtype=np.intc)
Out[24]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32)

要关闭它,请附加np.intcnp.core.numeric._typelessdata.

于 2017-09-18T19:13:16.253 回答