I have a bytes
element. My word size is 1, a single byte. The contents can be b'\xff\xff\x01'
meaning [-1, -1, 1]
.
I want to convert it to the int representation from the bytes form. Logically my attempt is:
ints = [int.from_bytes(j, byteorder='little', signed=True) for j in b'\xff\xff\x01']
TypeError: cannot convert 'int' object to bytes
However this does not work as the for j in bytes()
converts a bytes element directly into an int j
. This is however an unsigned conversion, I need signed. How do I convert my bytes, byte by byte, into a signed integer.
CodePudding user response:
However this does not work as the
for j in bytes()
converts a bytes element directly into an intj
.
As you've noticed, the bytes
is already an iterable over integer values. If we have a lot of data, it would be more memory efficient to keep the bytes
as is, and convert values on demand. We can simply do the math to convert the unsigned interpretation of a byte to the corresponding signed representation:
def signed_byte(b):
return b - 256 if b >= 128 else b
And wrap the indexing process:
def get_signed(data, index):
return signed_byte(data[index])
If we want or need to do all the conversion ahead of time, that feeds directly into the list comprehension:
ints = [signed_byte(b) for b in b'\xff\xff\x01']
On the other hand, we can reframe the question: to get a bytes
object from the original data as a subsequence (like how it worked in 2.x), we can use a 1-element slice instead; or we can wrap the int
value into a new bytes
. The former will be tricky to adapt to the original code, but the latter is trivial:
ints = [int.from_bytes(bytes([b]), byteorder='little', signed=True) for b in b'\xff\xff\x01']
CodePudding user response:
Another way, using Numpy:
>>> import numpy as np
>>> np.frombuffer(b'\xff\xff\x01', dtype=np.int8)
array([-1, -1, 1], dtype=int8)
CodePudding user response:
This solution is idiotic but at least it works.
data = b'\xff\xff\x01'
result = list(struct.unpack('b' * len(data), data))