184

我一直不确定我是否理解 str/unicode 解码和编码之间的区别。

我知道这str().decode()是因为当你有一个你知道具有某种字符编码的字节字符串时,考虑到该编码名称,它将返回一个 unicode 字符串。

我知道unicode().encode()根据给定的编码名称将 unicode 字符转换为字节串。

但我不明白什么str().encode()unicode().decode()是为了什么。任何人都可以解释,并可能纠正我在上面弄错的任何其他内容吗?

编辑:

几个答案提供了.encode关于字符串的作用的信息,但似乎没有人知道.decodeunicode 的作用。

4

6 回答 6

106

unicode 字符串的decode方法实际上根本没有任何应用程序(除非您出于某种原因在 unicode 字符串中有一些非文本数据——见下文)。我认为这主要是出于历史原因。在 Python 3 中,它完全消失了。

unicode().decode()将使用默认(ascii)编解码器执行隐式编码s像这样验证:

>>> s = u'ö'
>>> s.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

>>> s.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

错误消息完全相同。

因为str().encode()它是另一种方式 - 它尝试使用默认编码进行隐式解码:s

>>> s = 'ö'
>>> s.decode('utf-8')
u'\xf6'
>>> s.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)

这样用,str().encode()也是多余的。

但是后一种方法的另一个应用是有用的:有些编码与字符集无关,因此可以以有意义的方式应用于 8 位字符串:

>>> s.encode('zip')
'x\x9c;\xbc\r\x00\x02>\x01z'

不过,您是对的:这两个应用程序对“编码”的模棱两可的用法是……很尴尬。同样,在 Python 3 中使用单独的bytestring类型,这不再是一个问题。

于 2009-01-16T02:06:33.917 回答
70

将 unicode 字符串表示为字节字符串称为编码。使用u'...'.encode(encoding).

例子:

    >>> u'æøå'.encode('utf8')
    '\xc3\x83\xc2\xa6\xc3\x83\xc2\xb8\xc3\x83\xc2\xa5'
    >>> u'æøå'.encode('latin1')
    '\xc3\xa6\xc3\xb8\xc3\xa5'
    >>> u'æøå'.encode('ascii')
    UnicodeEncodeError:“ascii”编解码器无法对位置 0-5 中的字符进行编码:
    序数不在范围内(128)

您通常在需要将 unicode 字符串用于 IO 时对其进行编码,例如通过网络传输它,或将其保存到磁盘文件中。

将字节字符串转换为 unicode 字符串称为解码。使用unicode('...', encoding)或'...'。解码(编码)。

例子:

   >>> u'æøå'
   u'\xc3\xa6\xc3\xb8\xc3\xa5' # 解释器像这样打印 unicode 对象
   >>> unicode('\xc3\xa6\xc3\xb8\xc3\xa5', 'latin1')
   你'\xc3\xa6\xc3\xb8\xc3\xa5'
   >>> '\xc3\xa6\xc3\xb8\xc3\xa5'.decode('latin1')
   你'\xc3\xa6\xc3\xb8\xc3\xa5'

每当您从网络或磁盘文件接收到字符串数据时,您通常会解码一串字节。

我相信 python 3 中的 unicode 处理有一些变化,所以上述对于 python 3 可能不正确。

一些很好的链接:

于 2009-01-15T20:41:48.377 回答
16

一个Unicode。encode ('encoding') 产生一个字符串对象,可以在 unicode 对象上调用

一个字符串。decode ('encoding') 产生一个unicode对象,可以在字符串上调用,以给定的编码进行编码。


更多解释:

您可以创建一些没有任何编码集的 unicode 对象。Python 将它存储在内存中的方式与您无关。您可以搜索、拆分并调用您喜欢的任何字符串操作函数。

但是有一段时间,您想将 unicode 对象打印到控制台或某个文本文件中。所以你必须对其进行编码(例如 - 在 UTF-8 中),你调用 encode('utf-8') 并且你会得到一个内部带有 '\u<someNumber>' 的字符串,这是完全可打印的。

然后,再次 - 你想做相反的事情 - 读取以 UTF-8 编码的字符串并将其视为 Unicode,因此 \u360 将是一个字符,而不是 5。然后你解码一个字符串(使用选定的编码)和获取 unicode 类型的全新对象。

顺便说一句-您可以选择一些变态编码,例如“zip”、“base64”、“rot”,其中一些会从字符串转换为字符串,但我相信最常见的情况是涉及 UTF-8 /UTF-16 和字符串。

于 2009-01-16T23:11:40.193 回答
12

mybytestring.encode(somecodec) 对以下值有意义somecodec

  • base64
  • bz2
  • zlib
  • 十六进制
  • 夸普里
  • rot13
  • string_escape

我不确定解码已经解码的 unicode 文本有什么好处。尝试使用任何编码似乎总是首先尝试使用系统的默认编码进行编码。

于 2009-01-15T16:15:39.677 回答
5

有一些编码可用于从 str 到 str 或从 unicode 到 unicode 进行解码/编码。例如 base64、hex 甚至 rot13。它们列在编解码器模块中。

编辑:

unicode 字符串上的解码消息可以撤消相应的编码操作:

In [1]: u'0a'.decode('hex')
Out[1]: '\n'

返回的类型是 str 而不是 unicode,这在我看来是不幸的。但是,当您没有在 str 和 unicode 之间进行正确的编码/解码时,无论如何这看起来都是一团糟。

于 2009-01-15T15:20:41.053 回答
1

简单的答案是它们彼此完全相反。

计算机使用最基本的字节单位来存储和处理信息;对人眼来说是没有意义的。

例如,'\xe4\xb8\xad\xe6\x96\x87' 是两个汉字的表示,但计算机只有在给定字典查找时才知道(意味着打印或存储)它是汉字中文单词,在这种情况下,它是一个“utf-8”字典,如果您查看不同或错误的字典(使用不同的解码方法),它将无法正确显示预期的中文单词。

在上述情况下,计算机查找中文单词的过程是decode()

而计算机将中文写入计算机内存的过程是encode()

所以编码信息是原始字节,解码信息是原始字节和要引用的字典的名称(但不是字典本身)。

于 2018-01-03T07:16:42.207 回答