为什么 "bytes(n)" 创建一个长度为 n 的字节字符串,而不是将 n 转换为二进制表示形式?

14 浏览
0 Comments

为什么 "bytes(n)" 创建一个长度为 n 的字节字符串,而不是将 n 转换为二进制表示形式?

我试图在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'

我一直无法从文档中找到有关字节转换以这种方式工作的指针。然而,在这个关于在字节中添加format的Python问题中,我发现了一些令人惊讶的消息(参见Python 3 bytes formatting):

http://bugs.python.org/issue3982

这与字节(int)返回零的奇怪行为更加不兼容

还有:

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

有人能解释一下这种行为是从哪里来的吗?

admin 更改状态以发布 2023年5月23日
0
0 Comments

这样设计是有道理的,因为通常你会对一个可迭代对象调用 bytes 而不是单独的整数:

>>> bytes([3])
b'\x03'

Python 文档中有提到这一点,而且 bytes 函数的文档字符串也是这么写的:

>>> help(bytes)
...
bytes(int) -> bytes object of size given by the parameter initialized with null bytes

0
0 Comments

从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)

0