我正在使用一个返回“字节字符串”(bytes
)的库,我需要将其转换为字符串。
实际上这两者有什么区别吗?它们之间有什么关系,我该如何进行转换?
'I am a string'.encode('ASCII')
b'I am a string'.decode('ASCII')
'I am a string'
。>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'
.decode()
方法来获取正确的字符字符串,如上所示。为了完整起见,字符字符串的.encode()
方法则相反。>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
str
类型与bytes
类型是相同的;这个回答等价于将unicode
类型(在Python 3中不存在)与str
类型进行比较。 - craymichaelstr
对象的内存表示对于Python方面来说既不可访问也不相关;该数据结构只是一系列码位的序列。根据PEP 393,确切的内部编码是Latin-1、UCS2或UCS4之一,并且utf-8表示可以在首次请求后被缓存,但是即使是C代码也不鼓励依赖这些内部细节。 - lvc注意:由于Python 2的生命周期即将结束,因此我将更详细地解释Python 3的答案。
在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
>>> # 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
与运算符一起使用。str
和 unicode
之间进行转换可能会很有用,在 Python 3 中则是在 bytes
和 str
之间进行转换。我们来看一个单字符字符串'š'
,将其编码为一系列字节:
>>> 'š'.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))
'š'
来自什么是Unicode?:
基本上,计算机只处理数字。它们通过为每个字母和其他字符分配一个数字来存储这些字符。
......
Unicode为每个字符提供了唯一的数字,无论平台、程序或语言如何。
因此,当计算机表示字符串时,它通过它们独特的Unicode编号在计算机中找到字符串中的字符,并将这些数字存储在内存中。但是,您不能直接通过它们的独特Unicode编号将字符串写入磁盘或通过网络传输字符串,因为这些数字只是简单的十进制数。您应该将字符串编码为字节字符串,例如UTF-8。UTF-8是一种能够编码所有可能字符的字符编码,它将字符存储为字节(看起来像这样)。因此,编码后的字符串可以在任何地方使用,因为几乎所有地方都支持UTF-8。当您从其他系统打开以UTF-8编码的文本文件时,您的计算机将对其进行解码,并通过它们独特的Unicode编号显示其中的字符。
当浏览器从网络接收到以UTF-8编码的字符串数据时,它将解码数据为字符串(假设浏览器使用UTF-8编码)并显示该字符串。
在Python 3中,您可以相互转换字符串和字节字符串:
>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文
字符串是一堆项目串在一起。字节字符串是一系列字节,例如 b'\xce\xb1\xce\xac'
表示 "αά"
。字符字符串是一堆字符,例如 "αά"
。与序列同义。
字节字符串可以直接存储到磁盘上,而字符串(字符字符串)不能直接存储在磁盘上。它们之间的映射是编码。
str
和bytes
作为标准的“内置类型”。换句话说,它们都是类。我认为试图理解为什么Python被实现成这样并不值得。str
和bytes
非常相似。两者共享大部分相同的方法。以下方法是str
类独有的:casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable
bytes
类的:decode
fromhex
hex