在Python 3中,将字符串转换为字节的最佳方法?

从https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface 的答案中可以看出,似乎有两种不同的方法可以将字符串转换为字节。

哪种方法会更好或更符合Pythonic的要求?还是说这只是一个个人偏好的问题?

b = bytes(mystring, 'utf-8')

b = mystring.encode('utf-8')
对该问题的评论 (9)
解决办法

如果你看一下bytes的文档,它指向[bytearray](https://docs.python.org/3/library/functions.html#func-bytearray)。

bytearray([source[, encoding[, errors]])

返回一个新的字节数组。bytearray类型是一个范围在0<=x<256的可变整数序列。它具有大多数可变序列的通常方法,在可变序列类型中描述,以及字节类型具有的大多数方法,见字节和字节阵列方法。

可选的源参数可以用几种不同的方法来初始化数组。

__如果是一个字符串,你必须同时给出编码(和可选的错误)参数;bytearray()然后使用str.encode()将字符串转换为字节数。

__如果它是一个整数,数组将有这个大小,并将以空字节初始化。

__如果它是一个符合缓冲区接口的对象,该对象的一个只读缓冲区将被用来初始化字节数组。

如果它是一个可迭代的对象,它必须是一个范围为0 如果没有参数,将创建一个大小为0的数组。

所以bytes可以做的事情远不止是对字符串进行编码。这是Pythonic,它将允许你用任何类型的源参数来调用构造函数,这是有意义的。

对于字符串的编码,我认为some_string.encode(encoding)比使用构造函数更符合Pythonic的要求,因为它是最能自我记录的 -- "拿这个字符串用这个编码进行编码"比bytes(some_string, encoding)更清楚 -- 当你使用构造函数的时候没有明确的动词。

编辑:我检查了Python的源代码。如果你用CPython向bytes传递一个unicode字符串,它会调用PyUnicode_AsEncodedString,这是encode的实现;所以如果你自己调用encode,你只是跳过了一个层次的指示。

另外,请看Serdalis的评论 -- unicode_string.encode(encoding)也更符合Pythonic,因为它的逆向是byte_string.decode(encoding),对称性很好。

评论(5)

这比人们想象的要容易。

my_str = "hello world"
my_str_as_bytes = str.encode(my_str)
type(my_str_as_bytes) # ensure it is byte representation
my_decoded_str = my_str_as_bytes.decode()
type(my_decoded_str) # ensure it is string representation
评论(10)

绝对好的方法是这两个都不是,而是第三个。从Python 3.0开始,encode的第一个参数默认为*'utf-8'。因此,最好的方法是

b = mystring.encode()

这也会更快,因为默认参数的结果不是C代码中的字符串"utf-8",而是NULL,检查起来**快得多!

下面是一些时间安排。

In [1]: %timeit -r 10 'abc'.encode('utf-8')
The slowest run took 38.07 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 183 ns per loop

In [2]: %timeit -r 10 'abc'.encode()
The slowest run took 27.34 times longer than the fastest. 
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 137 ns per loop

尽管有警告,但反复运行后,时间非常稳定--偏差仅为~2%。


使用没有参数的encode()与Python 2不兼容,因为在Python 2中,默认字符编码是ASCII

>>> 'äöä'.encode()
Traceback (most recent call last):
  File "", line 1, in 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
评论(2)