我正在使用一个返回“字节字符串”(字节)的库,我需要将其转换为字符串。

这两者之间真的有区别吗?它们是如何关联的,我该如何进行转换?


当前回答

注意:我将详细阐述我对Python 3的回答,因为Python 2的生命周期已经非常接近了。

Python 3

bytes由8位无符号值的序列组成,而str由表示人类语言文本字符的Unicode码位序列组成。

>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve

尽管bytes和str看起来工作方式相同,但它们的实例彼此不兼容,即bytes和str实例不能与>和+等操作符一起使用。此外,请记住,比较bytes和str实例是否相等,即使用==,即使它们包含完全相同的字符,也将始终计算为False。

>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False

处理bytes和str的另一个问题是处理使用open内置函数返回的文件。一方面,如果你想从一个文件中读取或写入二进制数据,总是使用二进制模式打开文件,比如'rb'或'wb'。另一方面,如果要从文件中读取或写入Unicode数据,请注意计算机的默认编码,因此如果需要,可以传递encoding参数以避免意外。

在Python 2中

str由8位值的序列组成,而unicode由unicode字符的序列组成。需要记住的一点是,如果str仅由7位ASCI字符组成,则可以将str和unicode与操作符一起使用。

在Python 2中使用helper函数在str和unicode之间进行转换,在Python 3中使用bytes和str之间进行转换,可能会很有用。

其他回答

字符串是串在一起的一堆项目。字节串是一个字节序列,比如b'\xce\xb1\xce\xac'表示“α”。字符串是一串字符,比如“α”。序列的同义词。

字节串可以直接存储在磁盘上,而字符串(字符串)不能直接存储在磁盘上。它们之间的映射是一种编码。

让我们有一个简单的单字符字符串'š',并将其编码成一个字节序列:

>>> 'š'.encode('utf-8')
b'\xc5\xa1'

为了本例的目的,让我们以二进制形式显示字节序列:

>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'

现在,如果不知道信息是如何编码的,通常是不可能解码回信息的。只有当你知道使用了UTF-8文本编码时,你才能按照解码UTF-8的算法获得原始字符串:

11000101 10100001
   ^^^^^   ^^^^^^
   00101   100001

您可以将二进制数字101100001显示为字符串:

>>> chr(int('101100001', 2))
'š'

注意:我将详细阐述我对Python 3的回答,因为Python 2的生命周期已经非常接近了。

Python 3

bytes由8位无符号值的序列组成,而str由表示人类语言文本字符的Unicode码位序列组成。

>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve

尽管bytes和str看起来工作方式相同,但它们的实例彼此不兼容,即bytes和str实例不能与>和+等操作符一起使用。此外,请记住,比较bytes和str实例是否相等,即使用==,即使它们包含完全相同的字符,也将始终计算为False。

>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False

处理bytes和str的另一个问题是处理使用open内置函数返回的文件。一方面,如果你想从一个文件中读取或写入二进制数据,总是使用二进制模式打开文件,比如'rb'或'wb'。另一方面,如果要从文件中读取或写入Unicode数据,请注意计算机的默认编码,因此如果需要,可以传递encoding参数以避免意外。

在Python 2中

str由8位值的序列组成,而unicode由unicode字符的序列组成。需要记住的一点是,如果str仅由7位ASCI字符组成,则可以将str和unicode与操作符一起使用。

在Python 2中使用helper函数在str和unicode之间进行转换,在Python 3中使用bytes和str之间进行转换,可能会很有用。

Python语言包括str和bytes作为标准的“内置类型”。换句话说,它们都是类。我认为没有必要去解释为什么Python以这种方式实现。

尽管如此,str和bytes彼此非常相似。两者都有大部分相同的方法。下面的方法对于str类是唯一的:

casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable

以下方法对于bytes类是唯一的:

decode
fromhex
hex

简单地说,想想我们的自然语言,如英语、孟加拉语、汉语等。在说话时,所有这些语言都发出声音。但即使我们听到了,我们能听懂所有的吗?-

答案通常是否定的。所以,如果我说我懂英语,这意味着我知道这些声音是如何被编码成一些有意义的英语单词的,我只是用同样的方式解码这些声音来理解它们。所以,其他语言也是如此。如果你知道它,你就有了那种语言的编码器-解码器包,如果你不知道它,你就没有这个。

数字系统也是如此。就像我们自己一样,我们只能用耳朵听声音,用嘴巴发声,计算机只能存储字节和读取字节。因此,某个应用程序知道如何读取字节并解释它们(比如要考虑多少字节才能理解任何信息),并且以相同的方式编写,以便其其他应用程序也能理解它。但是如果没有理解(编码器-解码器),所有写入磁盘的数据都只是字节串。