Python создать массив структур

Structured arrays

Здесь x — одномерный массив длины два, тип данных которого представляет собой структуру с тремя полями: 1. Строка длиной 10 или меньше с именем «имя», 2. 32-битное целое число с именем «возраст» и 3. a 32-битное число с плавающей запятой с именем «вес».

Если вы индексируете x в позиции 1, вы получите структуру:

Вы можете получать доступ и изменять отдельные поля структурированного массива,индексируя их по имени поля:

>>> x['age'] array([9, 3], dtype=int32) >>> x['age'] = 5 >>> x array([('Rex', 5, 81.), ('Fido', 5, 27.)], dtype=[('name', '), ('age', '), ('weight', ')])

Структурированные типы данных разработаны таким образом,чтобы имитировать «структуры» в языке C,и имеют схожую структуру памяти.Они предназначены для взаимодействия с кодом на языке Си и для низкоуровневого манипулирования структурированными буферами,например,для интерпретации двоичных блоков.Для этих целей они поддерживают такие специализированные возможности,как подмассивы,вложенные типы данных и объединения,а также позволяют контролировать расположение структуры в памяти.

Пользователи,желающие манипулировать табличными данными,например,хранящимися в файлах csv,могут найти другие проекты pydata,такие как xarray,pandas или DataArray.Они предоставляют высокоуровневый интерфейс для анализа табличных данных и лучше оптимизированы для этого.Например,C-struct-подобная компоновка памяти структурированных массивов в numpy может привести к плохому поведению кэша в сравнении.

Structured Datatypes

Структурированный тип данных можно рассматривать как последовательность байтов определенной длины (размер элемента структуры), которая интерпретируется как набор полей. Каждое поле имеет имя, тип данных и смещение в байтах внутри структуры. Тип данных поля может быть любым типом данных numpy, включая другие структурированные типы данных, а также может быть типом данных подмассива, который ведет себя как ndarray указанной формы. Смещения полей произвольны, и поля могут даже перекрываться. Эти смещения обычно автоматически определяются numpy, но также могут быть указаны.

Создание структурированных типов данных

Структурированные типы данных могут быть созданы с помощью функции numpy.dtype . Есть 4 альтернативные формы спецификации, которые различаются по гибкости и лаконичности. Они дополнительно задокументированы на справочной странице по объектам типа данных , и в итоге они:

    Список кортежей,по одному кортежу на поле Каждый кортеж имеет форму (fieldname, datatype, shape) где форма не является обязательной. fieldname — это строка (или кортеж, если используются заголовки , см. Заголовки полей ниже), datatype может быть любой объект, конвертируемый в тип данных, а shape — кортеж целых чисел, определяющий форму подмассива.

>>> np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))]) dtype([('x', '), ('y', '), ('z', ', (2, 2))])

Если fieldname является пустой строкой » , полю будет присвоено имя по умолчанию в форме f# , где # — это целочисленный индекс поля, отсчитываемый от 0 слева:

>>> np.dtype([('x', 'f4'), ('', 'i4'), ('z', 'i8')]) dtype([('x', '), ('f1', '), ('z', ')])
>>> np.dtype('i8, f4, S3') dtype([('f0', '), ('f1', '), ('f2', 'S3')]) >>> np.dtype('3int8, float32, (2, 3)float64') dtype([('f0', 'i1', (3,)), ('f1', '), ('f2', ', (2, 3))])
>>> np.dtype('names': ['col1', 'col2'], 'formats': ['i4', 'f4']>) dtype([('col1', '), ('col2', ')]) >>> np.dtype('names': ['col1', 'col2'], . 'formats': ['i4', 'f4'], . 'offsets': [0, 4], . 'itemsize': 12>) dtype('names': ['col1', 'col2'], 'formats': [', '], 'offsets': [0, 4], 'itemsize': 12>)
>>> np.dtype('col1': ('i1', 0), 'col2': ('f4', 1)>) dtype([('col1', 'i1'), ('col2', ')])

Манипулирование и отображение структурированных типов данных

Список имен полей структурированного типа данных можно найти в names атрибутов объекта DTYPE:

>>> d = np.dtype([('x', 'i8'), ('y', 'f4')]) >>> d.names ('x', 'y')

Имена полей можно изменить, присвоив атрибуту names последовательность строк одинаковой длины.

Объект dtype также имеет атрибут, подобный словарю, fields , ключами которого являются имена полей (и заголовки полей , см. Ниже), а значениями являются кортежи, содержащие dtype и байтовое смещение каждого поля.

>>> d.fields mappingproxy('x': (dtype('int64'), 0), 'y': (dtype('float32'), 8)>)

И names и атрибуты fields будут равны None для неструктурированных массивов. Рекомендуемый способ проверить, структурирован ли dtype, — это if dt.names is not None а не if dt.names , чтобы учесть dtypes с 0 полями.

Строковое представление структурированного типа данных отображается в форме «список кортежей»,если это возможно,иначе numpy возвращается к использованию более общей формы словаря.

Автоматическое смещение и выравнивание байтов

Numpy использует один из двух методов для автоматического определения смещения байтов поля и общего размера элемента структурированного типа данных в зависимости от того, было ли указано align=True в качестве аргумента ключевого слова для numpy.dtype .

По умолчанию ( align=False ) numpy будет упаковывать поля вместе, так что каждое поле начинается с байтового смещения, в котором закончилось предыдущее поле, а поля в памяти являются смежными.

>>> def print_offsets(d): . print("offsets:", [d.fields[name][1] for name in d.names]) . print("itemsize:", d.itemsize) >>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2')) offsets: [0, 1, 2, 6, 7, 15] itemsize: 17

Если установлено align=True , numpy будет дополнять структуру так же, как многие компиляторы C дополняют C-структуру. В некоторых случаях выровненные структуры могут повысить производительность за счет увеличения размера типа данных. Байты заполнения вставляются между полями таким образом, что смещение каждого поля в байтах будет кратно выравниванию этого поля, которое обычно равно размеру поля в байтах для простых типов данных, см . PyArray_Descr.alignment . Структура также будет иметь завершающие отступы, чтобы ее размер элемента был кратным выравниванию самого большого поля.

>>> print_offsets(np.dtype('u1, u1, i4, u1, i8, u2', align=True)) offsets: [0, 1, 4, 8, 16, 24] itemsize: 32

Обратите внимание,что,хотя почти все современные компиляторы языка C по умолчанию выполняют такую разбивку,разбивка в структурах языка C зависит от реализации языка C,поэтому не гарантируется точное соответствие расположения памяти соответствующей структуре в программе на языке C.Для получения точного соответствия может потребоваться некоторая работа как на стороне numpy,так и на стороне C.

Если смещения были указаны с помощью дополнительного ключа offsets в спецификации dtype на основе словаря, установка align=True проверит, что смещение каждого поля кратно его размеру, а размер элемента кратен наибольшему размеру поля, и вызовет исключение. если не.

Если смещения полей и размер элементов структурированного массива удовлетворяют условиям выравнивания, для массива будет установлен flag ALIGNED .

Удобная функция numpy.lib.recfunctions.repack_fields преобразует выровненный dtype или массив в упакованный и наоборот. Он принимает либо dtype, либо структурированный ndarray в качестве аргумента и возвращает копию с переупакованными полями, с байтами заполнения или без них.

Field Titles

Помимо имен полей, поля могут также иметь связанный заголовок , альтернативное имя, которое иногда используется как дополнительное описание или псевдоним для поля. Заголовок может использоваться для индексации массива, как и имя поля.

Для добавления заголовков при использовании формы list-of-tuples спецификации dtype,имя поля может быть указано как кортеж из двух строк вместо одной строки,которые будут заголовком и именем поля соответственно.Например:

>>> np.dtype([(('my title', 'name'), 'f4')]) dtype([(('my title', 'name'), ')])

При использовании первой формы спецификации на основе словаря заголовки могут быть предоставлены как дополнительный ключ ‘titles’ как описано выше. При использовании второй (нежелательной) спецификации на основе словаря заголовок может быть предоставлен путем предоставления трехэлементного кортежа (datatype, offset, title) вместо обычного двухэлементного кортежа:

>>> np.dtype('name': ('i4', 0, 'my title')>) dtype([(('my title', 'name'), ')])

dtype.fields словарь будет содержать названия в качестве ключей, если используются какие — либо титулы. Фактически это означает, что поле с заголовком будет дважды представлено в словаре полей. Значения кортежа для этих полей также будут иметь третий элемент — заголовок поля. Из — за этого, и потому , что names атрибутов сохраняет порядок полей , а fields атрибута не может, рекомендуется перебирать полей DTYPE с использованием names атрибут DTYPE, который не будет список названий, как:

>>> for name in d.names: . print(d.fields[name][:2]) (dtype('int64'), 0) (dtype('float32'), 8)
NumPy 1.23

Массивы NumPy со структурированным dtype можно также рассматривать как recarray,где доступ к полю осуществляется,если бы оно было атрибутом.

Структурированные типы данных реализованы в numpy, чтобы по умолчанию иметь базовый numpy.void, но можно интерпретировать другое использование (base_dtype, форма спецификации

В качестве дополнительного удобства numpy предоставляет подкласс ndarray, numpy.recarray, который позволяет получить доступ к полям, структурированным по атрибутам, а не только по индексу.

Источник

Как объявить массив структур в Python (cypyton)

В общем проблема вот в чем.Есть некая библиотека которая импортирует структуры из С библиотеки с помощью ctypes.

В питоне соответственно создается класс структуры.

1 2 3 4 5 6 7 8 9 10 11 12 13
import ctypes as ct from J2534.dllLoader import MyDll PassThru_Data = (ct.c_ubyte * 4128) class PassThru_Msg(ct.Structure): _fields_ = [ ("ProtocolID", ct.c_ulong), ("RxStatus", ct.c_ulong), ("TxFlags", ct.c_ulong), ("Timestamp", ct.c_ulong), ("DataSize", ct.c_ulong), ("ExtraDataIndex",ct.c_ulong), ("Data", PassThru_Data)]

Вот тут эта структура наследуется классами.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
ptData = PassThru_Data class baseMsg(PassThru_Msg): def _setData(self, data): print (data) self.DataSize = len(data) self.Data = ptData() for i in range(self.DataSize): self.Data[i] = data[i] def setID(self, ID): d = Func.IntToID(ID) self._setData(d) def setIDandData(self, ID, data = []): d = Func.IntToID(ID) + data self._setData(d) class pt15765Msg(baseMsg): def __init__(self, TxFlag): self.ProtocolID = ProtocolID.ISO15765 self.TxFlags = TxFlag class ptMskMsg(pt15765Msg): pass class ptPatternMsg(pt15765Msg): pass class ptFlowControlMsg(pt15765Msg): pass class ptTxMsg(baseMsg): def __init__(self, ProtocolID, TxFlags): self.ProtocolID = ProtocolID self.TxFlags = TxFlags class ptRxMsg(baseMsg): def show(self): print(self.ProtocolID, self.RxStatus, self.Data[:self.DataSize])

Потом в файле я создаю переменную структуры и могу передавать её в функцию, использующую её, и назад функция мне возвращает массив данных в ней

msg = J2534.ptRxMsg() print(msg.Data[:100])

Это работает только для одного сообщения. в документации к библиотеки которая на написана на C есть такая выдержка
:

The PassThruWriteMsgs function is used to transmit network protocol messages over an existing logical
communication channel. The network protocol messages will flow from the User Application to the
PassThru device.

long PassThruWriteMsgs( unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout );

Parameters
ChannelID
The logical communication channel identifier assigned by the J2534 API/DLL when the communication
channel was opened via the PassThruConnect function.
pMsg
Pointer to the message structure containing the UserApplication transmit message(s).
For sending more than one message, this must be a pointer to an array of PASSTHRU_MSG structures.
Refer to PASSTHRU_MSG structure definition on page 46.

PNumMsgs
Pointer to the variable that contains the number of PASSTHRU_MSG structures that are allocated for
transmit frames. On function completion this variable will contain the actual number of messages sent to
the vehicle network. The transmitted number of messages may be less than the number requested by the
UserApplication.
Timeout
Timeout interval(in milliseconds) to wait for transmit completion. A value of zero instructs the API/DLL
to queue as many transmit messages as possible and return immediately. A nonzero timeout value
instructs the API/DLL to wait for the timeout interval to expire before returning. The API/DLL will not
wait the entire timeout interval if an error occurs or the specified number of messages have been sent.

Как я понимаю для того чтоб получить больше чем одно сообщение мне нужно объявить массив структур

В C это делается так :

Источник

Читайте также:  Css transform flip vertical
Оцените статью