杰瑞科技汇

Python字节如何转整数?

Of course! Converting a Python bytes object to an int is a common task, especially when dealing with network protocols, binary file formats, or cryptography. The primary and most recommended way to do this is using the int.from_bytes() method.

Python字节如何转整数?-图1
(图片来源网络,侵删)

Here’s a complete guide, from the basics to more advanced use cases.

The Recommended Method: int.from_bytes()

This is the built-in, Pythonic way to convert a bytes object into an integer. It's flexible and handles different byte orders (endianness) and signed/unsigned numbers.

Syntax

int.from_bytes(bytes, byteorder, *, signed=False)

Parameters

  • bytes: The bytes or bytearray object to convert.
  • byteorder: The order of bytes. This is crucial and can be one of two values:
    • 'big': Most significant byte (MSB) is at the beginning of the byte array (e.g., \x00\x01 is 1).
    • 'little': Least significant byte (LSB) is at the beginning of the byte array (e.g., \x01\x00 is 1).
  • signed (optional): A boolean indicating whether the number is two's complement signed or not.
    • False (default): The number is unsigned. The result will always be zero or positive.
    • True: The number is signed. The result can be negative if the most significant bit (MSB) of the byte sequence is set.

Examples

Let's use a sample byte sequence for most examples: my_bytes = b'\x01\x02\x03'

Unsigned Integer (Big-Endian)

This is the most common scenario for simple data representation.

Python字节如何转整数?-图2
(图片来源网络,侵删)
my_bytes = b'\x01\x02\x03'
# Big-endian: \x01 is the most significant byte
value = int.from_bytes(my_bytes, 'big')
print(f"Bytes: {my_bytes}")
print(f"Integer (big-endian, unsigned): {value}")
# Output: Integer (big-endian, unsigned): 66051

Calculation: (1 * 256^2) + (2 * 256^1) + (3 * 256^0) = 65536 + 512 + 3 = 66051

Unsigned Integer (Little-Endian)

The byte order is reversed.

my_bytes = b'\x01\x02\x03'
# Little-endian: \x03 is the most significant byte
value = int.from_bytes(my_bytes, 'little')
print(f"Bytes: {my_bytes}")
print(f"Integer (little-endian, unsigned): {value}")
# Output: Integer (little-endian, unsigned): 197121

Calculation: (3 * 256^2) + (2 * 256^1) + (1 * 256^0) = 196608 + 512 + 1 = 197121

Signed Integer (Big-Endian)

When signed=True, the function interprets the bytes as a two's complement number.

Python字节如何转整数?-图3
(图片来源网络,侵删)

Let's use a byte sequence where the most significant bit is 1, which typically indicates a negative number in two's complement.

# The hex value 0xFF is 255 in decimal. But in 8-bit two's complement,
# it represents -1.
my_bytes = b'\xff'
# Signed interpretation
value_signed = int.from_bytes(my_bytes, 'big', signed=True)
# Unsigned interpretation
value_unsigned = int.from_bytes(my_bytes, 'big', signed=False)
print(f"Bytes: {my_bytes}")
print(f"Integer (signed): {value_signed}")
print(f"Integer (unsigned): {value_unsigned}")
# Output:
# Integer (signed): -1
# Integer (unsigned): 255

Handling Different Lengths

The method works for any number of bytes.

# 1 byte
b1 = b'\x7f'
print(int.from_bytes(b1, 'big', signed=True)) # 127 (max positive 8-bit signed)
# 2 bytes
b2 = b'\xff\x7f'
print(int.from_bytes(b2, 'big', signed=True)) # 32767 (max positive 16-bit signed)
# 4 bytes
b4 = b'\x7f\xff\xff\xff'
print(int.from_bytes(b4, 'big', signed=True)) # 2147483647 (max positive 32-bit signed)
# 8 bytes
b8 = b'\x7f\xff\xff\xff\xff\xff\xff\xff'
print(int.from_bytes(b8, 'big', signed=True)) # 9223372036854775807 (max positive 64-bit signed)

The Reverse: int.to_bytes()

It's also useful to know how to go back from an integer to bytes.

my_int = 66051
# Convert back to 3 bytes, big-endian
bytes_big = my_int.to_bytes(3, 'big')
# Convert back to 3 bytes, little-endian
bytes_little = my_int.to_bytes(3, 'little')
print(f"Original Integer: {my_int}")
print(f"Bytes (big-endian): {bytes_big}")    # Output: b'\x01\x02\x03'
print(f"Bytes (little-endian): {bytes_little}") # Output: b'\x03\x02\x01'

You must specify the length (number of bytes). If the integer is too large to fit in the specified number of bytes, it will raise an OverflowError.

# This will fail because 300 requires 2 bytes, not 1.
try:
    300.to_bytes(1, 'big')
except OverflowError as e:
    print(e)
# Output: int too big to convert

Alternative (Manual) Method: Bit Shifting

For educational purposes or if you're working in an environment without int.from_bytes(), you can manually build the integer by iterating through the bytes and using bit shifting.

my_bytes = b'\x01\x02\x03'
byte_order = 'big' # or 'little'
result = 0
if byte_order == 'big':
    for byte in my_bytes:
        result = (result << 8) | byte
else: # little
    # Process bytes in reverse order for little-endian
    for byte in reversed(my_bytes):
        result = (result << 8) | byte
print(f"Integer (manual, {byte_order}-endian): {result}")
# Output: Integer (manual, big-endian): 66051

How it works:

  • result << 8: Shifts the current result 8 bits to the left (equivalent to multiplying by 256), making room for the next byte.
  • | byte: Performs a bitwise OR to add the new byte into the least significant 8 bits.

Why int.from_bytes() is better:

  • Readability: It's explicit and clear.
  • Conciseness: It's a single, simple function call.
  • Handles Signed Numbers: The manual method is significantly more complex to implement for signed two's complement numbers.
  • Performance: It's implemented in C and is highly optimized.

Summary: Which one should you use?

Method Use Case Pros Cons
int.from_bytes() Almost always. This is the standard, recommended way. Clean, readable, handles all cases (endianness, signed/unsigned), built-in, efficient. None for this task.
Bit Shifting Learning, interviews, or very constrained environments. Good for understanding the underlying process. Verbose, error-prone, especially for signed numbers.

Final Recommendation: Always use int.from_bytes() unless you have a very specific reason not to. It's the correct, safe, and Pythonic tool for the job.

分享:
扫描分享到社交APP
上一篇
下一篇