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

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问题中发现了一些关于向字节添加格式的令人惊讶的消息(另见Python 3字节格式化):

http://bugs.python.org/issue3982

这与bytes(int)返回零这样的奇怪情况的交互更加糟糕

and:

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

谁能给我解释一下这种行为是怎么来的?


当前回答

>>> chr(116).encode()
b't'

其他回答

如果问题是如何将一个整数本身(不是它的字符串等效)转换为字节,我认为健壮的答案是:

>>> i = 5
>>> i.to_bytes(2, 'big')
b'\x00\x05'
>>> int.from_bytes(i.to_bytes(2, 'big'), byteorder='big')
5

更多关于这些方法的信息:

https://docs.python.org/3.8/library/stdtypes.html#int.to_bytes https://docs.python.org/3.8/library/stdtypes.html#int.from_bytes

当你想要处理二进制表示时,最好使用ctypes。

import ctypes
x = ctypes.c_int(1234)
bytes(x)

你必须使用特定的整数表示(有符号/无符号和位数:c_uint8, c_int8, c_unit16,…)

这种行为源于这样一个事实:在Python版本3之前,bytes只是str的别名。X bytes是bytearray的不可变版本——全新的类型,不向后兼容。

这就是它的设计方式——这是有意义的,因为通常,你会在一个可迭代对象上调用bytes,而不是单个整数:

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

文档声明了这一点,以及字节的文档字符串:

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

Python 3.5+为字节引入了%-插值(printf风格的格式化):

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

参见PEP 0461—向bytes和bytearray添加%格式。

在早期版本中,你可以使用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' != b'\x03'
True