属性numpy.dtype.base的用途/状态

时间:2018-09-24 09:46:22

标签: python numpy

我在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版本的文档中也没有它:

我可以在以后的completiondate版本中依赖此属性的存在和行为吗?

3 个答案:

答案 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 dtypedtype.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.dtypecopy参数的文档,而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。