#python #numpy
#python #numpy #скаляр
Вопрос:
Я определил пользовательский dtype. Например:
vec = np.dtype([('x', float), ('y', float), ('z', float)])
quat = np.dtype([('w', float), ('v', vec)])
Теперь я хочу создать скалярный кватернион:
quat((1.0, (0.0, 0.0, 0.0)))
Я ожидал бы, что, во всяком случае, мой синтаксис кортежей неприемлем. Однако вместо этого я получаю следующую ошибку:
TypeError: 'numpy.dtype' object is not callable
Соответствующая часть документации по скалярам подразумевает, что возможно иметь скаляр структурированного типа, построенный подобным образом в numpy.
Как создать экземпляр quat
скаляра? Возможно ли это вообще?
Кстати, я поиграл со следующим обходным путем:
np.array([(1.0, (0.0, 0.0, 0.0))], dtype=quat)
Это не создает фактического скаляра (хотя, честно говоря, он работает достаточно хорошо для моих целей, что делает вопрос в основном теоретическим). Вызов item
результата возвращает a tuple
, а не скалярный quat
объект.
Комментарии:
1. Хотя
int
иnp.float32
может действовать какdtype
и функции для создания скаляра numpy, я не думаюnp.dtype
, что экземпляр может это сделать. У него нет__call__
метода (проверьте это).2. Составной dtype создает
np.void
объект. (или дляrecarray
anp.record
)3. @hpaulj. Я полностью согласен. Но, похоже, в документах есть какой -то способ. Я полагаю, если кто-нибудь знает, это будешь ты, Дивакар или около того.
4. @hpaulj. Так я и пытался сделать
quat.type(pack('dddd', 1.0, 0.0, 0.0, 0.0))
. Вероятно, это шаг в правильном направлении, но не совсем полезный в его необработанном виде5. @hpaulj. Понял:
quat.type(pack('dddd', 1.0, 0.0, 0.0, 0.0)).view(quat)
Ответ №1:
Вызов item
вашего массива привел к созданию кортежа, поскольку item
он специально разработан для преобразования типов NumPy в типы Python. Индексирование массива создает скаляр типа NumPy numpy.void
:
scalar = np.array([(1.0, (0.0, 0.0, 0.0))], dtype=quat)[0]
Комментарии:
1. Это действительно намного чище, чем моя версия. Спасибо.
Ответ №2:
Это основано на обсуждении в комментариях. Это более болезненно, чем должно быть, поскольку вряд ли найдется вариант использования для пользовательского скаляра, который не может быть решен более удобно с помощью массива из 1 элемента.
Тип quat
np.void
:
>>> quat.type
numpy.void
Поскольку это общий набор для пользовательских типов, он должен быть создан с помощью байтоподобного объекта:
>>> from struct import pack
>>> q = quat.type(pack('dddd', 1.0, 0.0, 0.0, 0.0))
>>> q
void(b'x00x00x00x00x00x00xF0x3Fx00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00')
И, конечно, поскольку это универсальный универсальный инструмент, вам нужно указать ему, как интерпретировать себя. К счастью, у скаляров также есть view
метод:
>>> q = q.view(quat)
>>> q
(1., (0., 0., 0.))
>>> q.dtype
dtype([('w', '<f8'), ('v', [('x', '<f8'), ('y', '<f8'), ('z', '<f8')])])
TL; DR
q = np.void(pack('dddd', 1.0, 0.0, 0.0, 0.0)).view(quat)