Назначение / статус атрибута numpy.dtype.base - PullRequest
0 голосов
/ 24 сентября 2018

Я нашел атрибут с именем 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 одного элемента для простых типов данных подмассива и самого себя для структурированных типов данных.

К сожалению, этот атрибутпохоже нигде не документировано.В документации есть a страница, но она пуста и нигде не связана.Любопытно, что он также отсутствует в документации для numpy версии 1.15.0, а именно:

Могу ли я рассчитывать на наличие и поведение этого атрибута вбудущие версии numpy?

Ответы [ 3 ]

0 голосов
/ 24 сентября 2018

Я никогда не использовал атрибут base или видел, что он использовал.Но имеет смысл, что должен быть способ идентификации такого объекта.Я не могу найти использование этого кода, такого как np.lib.recfunctions, но он вполне может быть использован в скомпилированном коде.

С dtype, подобным '10f8', существуют различные атрибуты (некоторые могут быть свойствами):

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, который мы получаем при просмотре только этого поля.

0 голосов
/ 24 сентября 2018

Я не уверен, безопасно ли полагаться на base, но, вероятно, это плохая идея в любом случае.Люди, читающие ваш код, не могут посмотреть, что означает base в документации, и в любом случае есть лучший вариант.

Вместо base вы можете использовать subdtype, который является документированным:

Tuple (item_dtype, shape), если этот dtype описывает подмассив, и None в противном случае.

Форма - это фиксированная форма подмассива, описанного этим типом данных, а item_dtype тип данных массива.

Еслиизвлекается поле, объект dtype которого имеет этот атрибут, затем дополнительные измерения, подразумеваемые shape , добавляются в конец полученного массива.

Для dtype, который представляетsubarray, 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 делает, вот источник , который подтверждает то, что вы угадали из своих экспериментов:

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);
}
0 голосов
/ 24 сентября 2018

*.base в numpy возвращает данные, на которые указывает их предшественник (если это действительно указатель).Так, например:

y = x[2:]
y.base is x
[Out]: True

Если вы не реализуете свой собственный dtype (в этом случае вы выходите из моей лиги программирования), это почти всегда будетбыть ссылкой на встроенный dtype (на основе документации параметра copy в numpy.dtype), а dtype(...).base будет тем встроенным dtype.

Хотя я не из тех, кто может предсказывать будущее, я думаю, что это связано с фундаментальной структурой данных, лежащей в основе ndarray, и поэтому вряд ли функциональность изменится в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...