杰瑞科技汇

Python中byte和int如何相互转换?

  • bytes 对象:是一个字节序列,每个字节是一个 8 位的无符号整数,范围是 0255
  • int 对象:是一个整数,可以表示任意大小的值。

转换的关键在于指定整数的字节顺序(大端序 Big-Endian 或小端序 Little-Endian)以及字节长度

Python中byte和int如何相互转换?-图1
(图片来源网络,侵删)

int 转换为 bytes (整数 -> 字节串)

使用 int 对象的 .to_bytes() 方法。

方法签名

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

参数说明

  • length: 整数转换后占用的字节数,如果指定的长度不足以表示整数,会抛出 OverflowError
  • byteorder: 字节顺序,可以是:
    • 'big': 大端序 (Big-Endian),最高有效字节 (MSB) 在最前面,整数 1 在 2 字节中表示为 b'\x00\x01'
    • 'little': 小端序 (Little-Endian),最低有效字节 (LSB) 在最前面,整数 1 在 2 字节中表示为 b'\x01\x00'
  • signed (可选): 布尔值,指定整数是否为有符号数。
    • False (默认): 无符号整数。
    • True: 有符号整数。

示例

示例 1: 无符号整数

# 将整数 255 转换为 1 个字节
num = 255
b1 = num.to_bytes(1, 'big')
print(f"整数 {num} -> 1字节 (大端): {b1}")
print(f"类型: {type(b1)}")
# 将整数 1 转换为 2 个字节 (大端序)
b2 = (1).to_bytes(2, 'big')
print(f"整数 1 -> 2字节 (大端): {b2}")
# 将整数 1 转换为 2 个字节 (小端序)
b3 = (1).to_bytes(2, 'little')
print(f"整数 1 -> 2字节 (小端): {b3}")

输出:

整数 255 -> 1字节 (大端): b'\xff'
类型: <class 'bytes'>
整数 1 -> 2字节 (大端): b'\x00\x01'
整数 1 -> 2字节 (小端): b'\x01\x00'

示例 2: 有符号整数

# 将有符号整数 -128 转换为 1 个字节
# 在二进制补码表示中,-128 的 1 字节表示是 0b10000000
signed_num = -128
b_signed = signed_num.to_bytes(1, 'big', signed=True)
print(f"有符号整数 {signed_num} -> 1字节: {b_signed}")
# 尝试将有符号整数 -129 转换为 1 个字节,会溢出
try:
    (-129).to_bytes(1, 'big', signed=True)
except OverflowError as e:
    print(f"错误: {e}")

输出:

有符号整数 -128 -> 1字节: b'\x80'
错误: int too big to convert

示例 3: 自动计算长度

如果你不确定需要多少字节,可以使用计算公式,对于有符号数,需要多一个符号位。

import math
num = 123456789
# 计算表示该无符号整数所需的最小字节数
length_unsigned = (num.bit_length() + 7) // 8
# num 是 0, bit_length() 是 0, 会得到 0, 所以需要特殊处理
if num == 0:
    length_unsigned = 1
b_auto = num.to_bytes(length_unsigned, 'big')
print(f"整数 {num} 自动计算长度 ({length_unsigned}字节): {b_auto}")
num_signed = -123456789
# 计算表示该有符号整数所需的最小字节数
length_signed = (num_signed.bit_length() + 8) // 8
if num_signed == 0:
    length_signed = 1
b_signed_auto = num_signed.to_bytes(length_signed, 'big', signed=True)
print(f"有符号整数 {num_signed} 自动计算长度 ({length_signed}字节): {b_signed_auto}")

输出:

整数 123456789 自动计算长度 (4字节): b'\x07\x5b\xcd\x15'
有符号整数 -123456789 自动计算长度 (4字节): b'\xf8\xa2\x32\xeb'

bytes 转换为 int (字节串 -> 整数)

使用 int 构造函数,传入 bytes 对象。

方法签名

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

参数说明

  • bytes: 要转换的 bytes 对象。
  • byteorder: 字节顺序,与 .to_bytes() 方法中的含义相同,'big''little'
  • signed (可选): 布尔值,指定字节序列是否表示一个有符号整数。

示例

示例 1: 无符号整数

# 从 1 字节转换
b_val = b'\xff'
num1 = int.from_bytes(b_val, 'big')
print(f"字节 {b_val} -> 整数 (大端): {num1}")
# 从 2 字节转换 (大端序)
b_val_big = b'\x00\x01'
num2 = int.from_bytes(b_val_big, 'big')
print(f"字节 {b_val_big} -> 整数 (大端): {num2}")
# 从 2 字节转换 (小端序)
b_val_little = b'\x01\x00'
num3 = int.from_bytes(b_val_little, 'little')
print(f"字节 {b_val_little} -> 整数 (小端): {num3}")

输出:

字节 b'\xff' -> 整数 (大端): 255
字节 b'\x00\x01' -> 整数 (大端): 1
字节 b'\x01\x00' -> 整数 (小端): 1

示例 2: 有符号整数

# 从 1 字节转换,解释为有符号数
# b'\x80' 在二进制补码中代表 -128
b_signed = b'\x80'
num_signed = int.from_bytes(b_signed, 'big', signed=True)
print(f"字节 {b_signed} -> 有符号整数 (大端): {num_signed}")
# 同样的字节,解释为无符号数就是 128
num_unsigned = int.from_bytes(b_signed, 'big', signed=False)
print(f"字节 {b_signed} -> 无符号整数 (大端): {num_unsigned}")

输出:

字节 b'\x80' -> 有符号整数 (大端): -128
字节 b'\x80' -> 无符号整数 (大端): 128

示例 3: 多字节序列

# 一个 4 字节的序列
data = b'\x12\x34\x56\x78'
# 大端序解释
big_endian_num = int.from_bytes(data, 'big')
print(f"字节 {data} (大端) -> 整数: {big_endian_num}")
# 小端序解释
little_endian_num = int.from_bytes(data, 'little')
print(f"字节 {data} (小端) -> 整数: {little_endian_num}")

输出:

字节 b'\x12\x34\x56\x78' (大端) -> 整数: 305419896
字节 b'\x12\x34\x56\x78' (小端) -> 整数: 2025915346

计算验证 (小端序 b'\x12\x34\x56\x78'): 0x78 (256⁰) + 0x56 (256¹) + 0x34 (256²) + 0x12 (256³) = 120 + 21504 + 1392640 + 202526592 = 2025915346


总结与最佳实践

转换方向 方法 关键点
int -> bytes my_int.to_bytes(length, 'big/little', signed=...) 必须指定长度,2. 必须指定字节顺序,3. 明确是否为有符号数
bytes -> int int.from_bytes(my_bytes, 'big/little', signed=...) 必须指定字节顺序,2. 必须明确是否为有符号数,否则默认为无符号。

重要提示:

  • 字节顺序是关键:在处理网络协议(如 TCP/IP)时,通常使用大端序,而在许多本地架构(如 x86 CPU)中,内存存储使用小端序,确保通信双方使用相同的字节顺序。
  • 长度和符号:转换时,lengthsigned 参数必须匹配数据的原始含义,错误地解释一个有符号数为无符号数会导致完全错误的结果(b'\xff' 会被解释为 255 而不是 -1)。
  • Python 3 的优势:Python 3 的 bytesint 类型处理非常清晰,避免了 Python 2 中 strbytes 混用带来的混乱,在 Python 3 中,bytes 专门用于二进制数据,str 用于文本。
分享:
扫描分享到社交APP
上一篇
下一篇