在 Python 3 中将 int 转换为字节

新手上路,请多包涵

我试图在 Python 3 中构建这个字节对象:

b'3\r\n'

所以我尝试了明显的(对我来说),并发现了一个奇怪的行为:

 >>> bytes(3) + b'\r\n'
b'\x00\x00\x00\r\n'

显然:

 >>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

在阅读文档时,我一直无法看到任何关于字节转换为何以这种方式工作的指针。但是,我确实在这个 Python 问题中发现了一些关于将 format 添加到字节的令人惊讶的消息(另请参见 Python 3 bytes formatting ):

http://bugs.python.org/issue3982

这与现在返回零的字节(int)之类的奇怪交互更差

和:

如果 bytes(int) 返回该 int 的 ASCII 化,对我来说会更方便;但老实说,即使是错误也会比这种行为更好。 (如果我想要这种行为——我从来没有过——我宁愿它是一个类方法,像“bytes.zeroes(n)”一样调用。)

有人可以解释一下这种行为的来源吗?

原文由 astrojuanlu 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 922
2 个回答

Python 3.5+ 为字节引入了 %-interpolation ( printf -style 格式)

 >>> b'%d\r\n' % 3
b'3\r\n'

请参阅 PEP 0461 - 向字节和字节数组添加 % 格式

在早期版本中,您可以使用 str.encode('ascii') 结果:

 >>> s = '%d\r\n' % 3
>>> s.encode('ascii')
b'3\r\n'

注意:它与 int.to_bytes 产生 的不同:

 >>> n = 3
>>> n.to_bytes((n.bit_length() + 7) // 8, 'big') or b'\0'
b'\x03'
>>> b'3' == b'\x33' != '\x03'
True

原文由 jfs 发布,翻译遵循 CC BY-SA 3.0 许可协议

从 python 3.2 开始,您可以使用 to_bytes

 >>> (1024).to_bytes(2, byteorder='big')
b'\x04\x00'

 def int_to_bytes(x: int) -> bytes:
    return x.to_bytes((x.bit_length() + 7) // 8, 'big')

def int_from_bytes(xbytes: bytes) -> int:
    return int.from_bytes(xbytes, 'big')

因此, x == int_from_bytes(int_to_bytes(x)) 。请注意,上述编码仅适用于无符号(非负)整数。

对于有符号整数,位长的计算有点棘手:

 def int_to_bytes(number: int) -> bytes:
    return number.to_bytes(length=(8 + (number + (number < 0)).bit_length()) // 8, byteorder='big', signed=True)

def int_from_bytes(binary_data: bytes) -> Optional[int]:
    return int.from_bytes(binary_data, byteorder='big', signed=True)

原文由 brunsgaard 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题