我在base
个对象上发现了一个名为numpy.dtype
的属性。做一些实验:
numpy.dtype('i4').base
# dtype('int32')
numpy.dtype('6i4').base
# dtype('int32')
numpy.dtype('10f8').base
# dtype('float64')
numpy.dtype('3i4, 2f4')
# dtype([('f0', '<i4', (3,)), ('f1', '<f4', (2,))])
因此,对于简单的子数组数据类型,它似乎包含单个元素的dtype
;对于结构化数据类型,它本身包含numpy
。
不幸的是,似乎没有任何地方记录该属性。 {em> 是page in the documentation,但它为空,没有链接到任何地方。奇怪的是,numpy
1.15.0版本的文档中也没有它:
/doc/numpy/…/numpy.dtype.base.html
(空白页)/doc/numpy-1.15.0/…/numpy.dtype.base.html
(错误404)/doc/numpy-1.15.1/…/numpy.dtype.base.html
(空白页)我可以在以后的completiondate
版本中依赖此属性的存在和行为吗?
答案 0 :(得分:1)
我不确定依靠base
是否安全,但是无论哪种方式都可能是个坏主意。读取您的代码的人无法查看base
在文档中的含义,无论如何,还有更好的选择。
您可以使用subdtype
代替base
,该文件记录了 :
元组
(item_dtype, shape)
(如果此dtype描述了一个 子数组,否则为None。shape 是此数据描述的子数组的固定形状 类型和 item_dtype 数组的数据类型。
如果检索到其dtype对象具有此属性的字段,则 shape 所隐含的额外尺寸标注在 检索到的数组。
对于表示子数组的dtype,dtype.base
等效于dtype.subdtype[0]
。对于不代表子数组的dtype,请使用dtype.base is dtype
和dtype.subdtype is None
。这是一个演示:
>>> subarray = numpy.dtype('5i4')
>>> not_subarray = numpy.dtype('i4')
>>> subarray.base
dtype('int32')
>>> subarray.subdtype
(dtype('int32'), (5,))
>>> not_subarray.base
dtype('int32')
>>> print(not_subarray.subdtype) # None doesn't get auto-printed
None
顺便说一句,如果您想确定dtype.base
所做的事情,请here's the source,以确认您从实验中得出的结论:
static PyObject *
arraydescr_base_get(PyArray_Descr *self)
{
if (!PyDataType_HASSUBARRAY(self)) {
Py_INCREF(self);
return (PyObject *)self;
}
Py_INCREF(self->subarray->base);
return (PyObject *)(self->subarray->base);
}
答案 1 :(得分:0)
*.base
中的 numpy
返回其先行指向的数据(如果确实是指针)。因此,for instance:
y = x[2:]
y.base is x
[Out]: True
除非您要实现自己的自定义dtype
(在这种情况下您不属于我的编程联盟),否则几乎总是引用内置dtype
(基于numpy.dtype
中copy
参数的文档,而dtype(...).base
将是内置的dtype
。
虽然我不是一个可以预测未来的人,但我想这与ndarray
底层的基本数据结构有关,因此将来的功能不太可能改变。
答案 2 :(得分:0)
我从未使用过base
属性,也从未见过使用它。但是,确实应该有一种识别此类对象的方式是有意义的。我找不到在np.lib.recfunctions
中使用它的代码,但是它很可能在编译后的代码中使用。
使用dtype(例如“ 10f8”)时,会出现各种attritube(可能是一些属性):
In [259]: dt = np.dtype('10f8')
In [260]: dt
Out[260]: dtype(('<f8', (10,)))
In [261]: dt.base
Out[261]: dtype('float64')
In [263]: dt.descr
Out[263]: [('', '|V80')]
In [264]: dt.itemsize
Out[264]: 80
In [265]: dt.shape
Out[265]: (10,)
看看当我们使用此dtype创建数组时会发生什么:
In [278]: x = np.ones((3,),'10f8')
In [279]: x
Out[279]:
array([[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]])
In [280]: x.shape
Out[280]: (3, 10)
In [281]: x.dtype
Out[281]: dtype('float64') # there's your base
答案是-dt.base
是将用于创建具有dtype的数组的dtype。是没有额外维信息的dtype。
这种dtype很少单独使用;更有可能是复合dtype的一部分:
In [252]: dt=np.dtype('3i4, 2f4')
In [253]: dt
Out[253]: dtype([('f0', '<i4', (3,)), ('f1', '<f4', (2,))])
In [254]: dt.base
Out[254]: dtype([('f0', '<i4', (3,)), ('f1', '<f4', (2,))])
In [255]: dt[0]
Out[255]: dtype(('<i4', (3,)))
In [256]: dt[0].base
此dt
可以嵌入另一个dtype中:
In [272]: dt1 = np.dtype((dt, (3,)))
In [273]: dt1
Out[273]: dtype(([('f0', '<i4', (3,)), ('f1', '<f4', (2,))], (3,)))
In [274]: dt1.base
Out[274]: dtype([('f0', '<i4', (3,)), ('f1', '<f4', (2,))])
In [275]: arr = np.ones((3,), dt1)
In [276]: arr
Out[276]:
array([[([1, 1, 1], [1., 1.]), ([1, 1, 1], [1., 1.]),
([1, 1, 1], [1., 1.])],
[([1, 1, 1], [1., 1.]), ([1, 1, 1], [1., 1.]),
([1, 1, 1], [1., 1.])],
[([1, 1, 1], [1., 1.]), ([1, 1, 1], [1., 1.]),
([1, 1, 1], [1., 1.])]],
dtype=[('f0', '<i4', (3,)), ('f1', '<f4', (2,))])
In [277]: arr.shape
Out[277]: (3, 3)
对于结构化数组,字段的基础是仅查看该字段时获得的dtype。