Ответ 1
Свен отвечает. Однако в Python также возможны числа смещения байтов (как и в вашем вопросе):
>>> [hex(0x12345678 >> i & 0xff) for i in (24,16,8,0)]
['0x12', '0x34', '0x56', '0x78']
Мне нужно отправить сообщение байтов в Python, и мне нужно преобразовать целое число без знака в массив байтов. Как преобразовать целочисленное значение в массив из четырех байтов в Python? Как в C:
uint32_t number=100;
array[0]=(number >>24) & 0xff;
array[1]=(number >>16) & 0xff;
array[2]=(number >>8) & 0xff;
array[3]=number & 0xff;
Может ли кто-нибудь показать мне, как? Мне сначала странно программировать без типов.
Свен отвечает. Однако в Python также возможны числа смещения байтов (как и в вашем вопросе):
>>> [hex(0x12345678 >> i & 0xff) for i in (24,16,8,0)]
['0x12', '0x34', '0x56', '0x78']
Посмотрите на модуль struct
. Вероятно, вам нужно всего struct.pack("I", your_int)
, чтобы упаковать целое число в строку, а затем поместите эту строку в сообщение. Строка формата "I"
обозначает 32-разрядное целое без знака.
Если вы хотите распаковать такую строку на кортеж для целых чисел, вы можете использовать struct.unpack("4b", s)
:
>>> struct.unpack("4b", struct.pack("I", 100))
(100, 0, 0, 0)
(Пример, очевидно, на машине маленького конца.)
Если кто-нибудь посмотрит на этот вопрос когда-нибудь позже...
Это утверждение должно быть эквивалентно коду в исходном вопросе:
>>> tuple( struct.pack("!I", number) )
('\x00', '\x00', '\x00', 'd')
И я не думаю, что это важно, что такое порядок байтов хоста.
Если ваши целые числа больше, чем int32, вы можете использовать "!Q"
в вызове pack()
для int64 (если ваша система поддерживает Q
).
И list()
или даже bytearray()
будет работать вместо tuple()
.
Обратите внимание: результатом является последовательность объектов str
(каждая из которых содержит один байт), а не целые числа. Если у вас должен быть список целых чисел, вы можете сделать это:
[ ord(c) for c in struct.pack("!I", number) ]
[0, 0, 0, 100]
... или это:
>>> map( ord, tuple( struct.pack("!I", number) ) )
[0, 0, 0, 100]
Но использование map()
начинает делать вещи немного грязными.
Это своего рода старый поток, но в Python 3.2+ теперь вы можете просто сказать:
number = 100
number.to_bytes(4, byteorder = 'big')
или byteorder = 'little'
в соответствии с вашими потребностями. Документация здесь.
Вы можете в значительной степени сделать то же самое:
>>> number = 100
>>> array[0] = (number>>24) & 0xff
>>> array[1] = (number>>16) & 0xff
>>> array[2] = (number>>8) & 0xff
>>> array[3] = number & 0xff
или вы можете сделать что-то более короткое:
>>> array = [(number>>(8*i))&0xff for i in range(3,-1,-1)]
И для полноты: вы также можете использовать модуль array
:
>>> from array import array
>>> a = array('I', [100]) # note that 'I' and such are machine-dependent.
>>> a.tostring()
'\d\x00\x00\x00'
>>> a.byteswap()
>>> a.tostring()
'\x00\x00\x00\d'
Это можно сделать и с помощью ctypes
. Это особенно полезно для преобразования чисел с плавающей точкой в байты. Пример:
>>> bytes(ctypes.c_uint32(0x20))
b' \x00\x00\x00'
>>> bytes(ctypes.c_double(1))
b'\x00\x00\x00\x00\x00\x00\xf0?'