杰瑞科技汇

Python字节与整数如何转换?

Of course! This is a fundamental concept in Python, especially when dealing with low-level data, networking, or file I/O. Let's break it down.

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

The Core Idea: Bytes vs. Integers

In Python, there are two main data types to understand here:

  1. int (Integer): This is a standard integer that can be of any size. It's a high-level, abstract representation of a whole number.

    • 255, 0, 42, 12345678901234567890 are all ints.
  2. bytes (Bytes Object): This is a sequence of immutable bytes (8-bit values). Each byte in the sequence can only hold a value from 0 to 255. It's a low-level, concrete representation of data.

    • b'\xff', b'\x00\x01\x02', b'hello' are all bytes objects.

The key is that a single byte can represent an integer from 0 to 255. The process of converting between an int and a bytes object is called serialization or encoding (for int to bytes) and deserialization or decoding (for bytes to int).

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

Converting an Integer to Bytes (int -> bytes)

You use the .to_bytes() method of an integer. This is the most common and Pythonic way.

The Syntax:

int.to_bytes(length, byteorder, *, signed=False)

The Parameters:

  • length: The number of bytes to use to represent the integer. This is crucial. If the integer is too large to fit in the specified number of bytes, you'll get an OverflowError.
  • byteorder: The order of the bytes in the resulting sequence.
    • 'big': Most significant byte (MSB) first. (Network byte order, or "big-endian").
    • 'little': Least significant byte (LSB) first. (Little-endian, common on Intel/AMD processors).
  • signed (optional): A boolean.
    • False (default): The integer is treated as unsigned (must be 0 or positive).
    • True: The integer is treated as signed (can be negative).

Examples:

Example 1: Simple Unsigned Integer

Let's convert the integer 255 to a single byte.

my_int = 255
# Convert to 1 byte, big-endian, unsigned
bytes_big = my_int.to_bytes(1, 'big')
print(f"Integer: {my_int}")
print(f"As bytes (big-endian): {bytes_big}")
print(f"Type: {type(bytes_big)}")
# Output:
# Integer: 255
# As bytes (big-endian): b'\xff'
# Type: <class 'bytes'>
# Convert to 1 byte, little-endian, unsigned
bytes_little = my_int.to_bytes(1, 'little')
print(f"As bytes (little-endian): {bytes_little}")
# Output:
# As bytes (little-endian): b'\xff'
# (For a single byte, the order doesn't matter)

Example 2: Integer Requiring Multiple Bytes

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

Let's convert the integer 305419896 (which is 0x12345678 in hex).

my_int = 305419896
# Using 4 bytes
bytes_big = my_int.to_bytes(4, 'big')
print(f"Integer: {my_int} (0x{my_int:x})")
print(f"As 4 bytes (big-endian): {bytes_big}")
# Output:
# Integer: 305419896 (0x12345678)
# As 4 bytes (big-endian): b'\x12\x34\x56\x78'
bytes_little = my_int.to_bytes(4, 'little')
print(f"As 4 bytes (little-endian): {bytes_little}")
# Output:
# As 4 bytes (little-endian): b'\x78\x56\x34\x12'

Example 3: Signed Negative Integer

Let's convert -42 to 2 bytes.

my_int = -42
# We need at least 2 bytes to represent -42 in two's complement form.
bytes_signed = my_int.to_bytes(2, 'big', signed=True)
print(f"Integer: {my_int}")
print(f"As 2 signed bytes (big-endian): {bytes_signed}")
# Output:
# Integer: -42
# As 2 signed bytes (big-endian): b'\xd6\xff'
# (0xffd6 is the two's complement representation of -42)

Converting Bytes to an Integer (bytes -> int)

You use the built-in int.from_bytes() class method. This is the reverse operation.

The Syntax:

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

The Parameters:

  • bytes: The bytes object to convert.
  • byteorder: The order of the bytes in the input sequence ('big' or 'little').
  • signed (optional): A boolean indicating whether the integer is signed or not. This must match how the bytes were created.

Examples:

Example 1: Converting Back from Example 1

bytes_data = b'\xff'
# Convert from big-endian, unsigned
my_int = int.from_bytes(bytes_data, 'big', signed=False)
print(f"Bytes: {bytes_data}")
print(f"As integer (unsigned): {my_int}")
# Output:
# Bytes: b'\xff'
# As integer (unsigned): 255
# Convert from little-endian, unsigned
# (Result is the same for a single byte)
my_int_little = int.from_bytes(bytes_data, 'little', signed=False)
print(f"As integer (little-endian): {my_int_little}")
# Output:
# As integer (little-endian): 255

Example 2: Converting Back from Example 2

bytes_big = b'\x12\x34\x56\x78'
bytes_little = b'\x78\x56\x34\x12'
my_int_from_big = int.from_bytes(bytes_big, 'big')
my_int_from_little = int.from_bytes(bytes_little, 'little')
print(f"From big-endian bytes: {my_int_from_big}")
print(f"From little-endian bytes: {my_int_from_little}")
# Output:
# From big-endian bytes: 305419896
# From little-endian bytes: 305419896

Example 3: Converting Back from Example 3

bytes_signed = b'\xd6\xff'
my_int_signed = int.from_bytes(bytes_signed, 'big', signed=True)
print(f"From signed bytes: {my_int_signed}")
# Output:
# From signed bytes: -42

The struct Module (For More Complex Cases)

When you're dealing with binary data formats (like network protocols or binary file formats), the struct module is extremely powerful. It allows you to pack and unpack C-style data structures (which are just bytes) into Python types.

The struct module uses format strings to define the layout of the data.

  • I: Unsigned Integer (typically 4 bytes)
  • i: Signed Integer (typically 4 bytes)
  • H: Unsigned Short (typically 2 bytes)
  • B: Unsigned Char (1 byte)
  • >: Big-endian
  • <: Little-endian

Example: Packing and Unpacking

Let's pack the integer 305419896 into 4 bytes, then unpack it back.

import struct
my_int = 305419896
# Pack the integer into 4 bytes, big-endian
# The format string is '>I' (Big-endian, Unsigned Integer)
packed_bytes = struct.pack('>I', my_int)
print(f"Packed bytes: {packed_bytes}")
# Output:
# Packed bytes: b'\x12\x34\x56\x78'
# Unpack the bytes back into an integer
# The format string must match the packed format
unpacked_int = struct.unpack('>I', packed_bytes)[0] # [0] because unpack returns a tuple
print(f"Unpacked integer: {unpacked_int}")
# Output:
# Unpacked integer: 305419896

Summary Table

Task Method / Function Example
int -> bytes int.to_bytes(length, byteorder, signed=False) to_bytes(1, 'big') -> b'\xff'
bytes -> int int.from_bytes(bytes, byteorder, signed=False) int.from_bytes(b'\xff', 'big') -> 255
int <-> bytes (C-style) struct.pack() / struct.unpack() struct.pack('>I', 123) -> b'\x00\x00\x00{'
Working with single byte int.to_bytes(1, ...) to_bytes(1, 'big') -> b'*'
Working with single byte int.from_bytes(b'*', ...) int.from_bytes(b'*', 'big') -> 42

Key Takeaways

  1. bytes is a sequence of 8-bit values (0-255). An int is a single abstract number.
  2. Use .to_bytes() and int.from_bytes() for direct, simple conversions.
  3. Always specify the length and byteorder correctly. Mismatched byteorders are a common source of bugs.
  4. Use the signed parameter consistently when dealing with negative numbers.
  5. For complex binary data, the struct module is your best friend.
分享:
扫描分享到社交APP
上一篇
下一篇