gpt4 book ai didi

python 3 : Demystifying encode and decode methods

转载 作者:太空狗 更新时间:2023-10-29 17:55:33 25 4
gpt4 key购买 nike

假设我在 Python 中有一个字符串:

>>> s = 'python'
>>> len(s)
6

现在我像这样编码这个字符串:

>>> b = s.encode('utf-8')
>>> b16 = s.encode('utf-16')
>>> b32 = s.encode('utf-32')

我从上面的操作中得到的是一个字节数组——也就是说,bb16b32 只是字节数组(当然,每个字节都是 8 位长)。

但我们对字符串进行了编码。那么这是什么意思?我们如何将“编码”的概念附加到原始字节数组?

答案在于这些字节数组中的每一个都是以特定方式生成的。让我们看看这些数组:

>>> [hex(x) for x in b]
['0x70', '0x79', '0x74', '0x68', '0x6f', '0x6e']

>>> len(b)
6

这个数组表示对于每个字符我们有一个字节(因为所有字符都在 127 以下)。因此,我们可以说将字符串“编码”为“utf-8”会收集每个字符对应的代码点并将其放入数组中。如果代码点不能放在一个字节中,那么 utf-8 会占用两个字节。因此 utf-8 消耗尽可能少的字节数。

>>> [hex(x) for x in b16]
['0xff', '0xfe', '0x70', '0x0', '0x79', '0x0', '0x74', '0x0', '0x68', '0x0', '0x6f', '0x0', '0x6e', '0x0']

>>> len(b16)
14 # (2 + 6*2)

在这里我们可以看到,“编码为 utf-16”首先将两个字节的 BOM (FF FE) 放入字节数组中,然后,对于每个字符,它将两个字节放入大批。 (在我们的例子中,第二个字节总是零)

>>> [hex(x) for x in b32]
['0xff', '0xfe', '0x0', '0x0', '0x70', '0x0', '0x0', '0x0', '0x79', '0x0', '0x0', '0x0', '0x74', '0x0', '0x0', '0x0', '0x68', '0x0', '0x0', '0x0', '0x6f', '0x0', '0x0', '0x0', '0x6e', '0x0', '0x0', '0x0']

>>> len(b32)
28 # (2+ 6*4 + 2)

在“utf-32 编码”的情况下,我们首先放入 BOM,然后为每个字符放入四个字节,最后将两个零字节放入数组中。

因此,我们可以说“编码过程”为字符串中的每个字符收集 1、2 或 4 个字节(取决于编码名称),并在它们前面添加和追加更多字节以创建最终的字节结果数组。

现在,我的问题:

  • 我对编码过程的理解正确还是我遗漏了什么?
  • 我们可以看到变量bb16b32的内存表示实际上是一个字节列表。字符串的内存表示是什么?字符串在内存中究竟存储了什么?
  • 我们知道当我们做一个encode()时,每个字符对应的代码点被收集(代码点对应于编码名称)并放入一个数组或字节中。当我们执行 decode() 时到底发生了什么?
  • 我们可以看到在utf-16和utf-32中,前置了一个BOM,但是为什么在utf-32编码中附加了两个零字节呢?

最佳答案

首先,UTF-32是一个4字节的编码,所以它的BOM也是一个四字节的序列:

>>> import codecs
>>> codecs.BOM_UTF32
b'\xff\xfe\x00\x00'

并且由于不同的计算机体系结构以不同方式处理字节顺序(称为 Endianess ),因此 BOM 有两种变体,小端和大端:

>>> codecs.BOM_UTF32_LE
b'\xff\xfe\x00\x00'
>>> codecs.BOM_UTF32_BE
b'\x00\x00\xfe\xff'

BOM 的目的是将该订单传达给解码器;阅读 BOM,您知道它是大端还是小端。因此,UTF-32 字符串中的最后两个空字节是最后编码字符的一部分。

UTF-16因此,BOM 很相似,因为有两种变体:

>>> codecs.BOM_UTF16
b'\xff\xfe'
>>> codecs.BOM_UTF16_LE
b'\xff\xfe'
>>> codecs.BOM_UTF16_BE
b'\xfe\xff'

默认使用哪一个取决于您的计算机架构。

UTF-8根本不需要 BOM; UTF-8 每个字符使用 1 个或多个字节(根据需要添加字节以编码更复杂的值),但这些字节的顺序在标准中定义。 Microsoft 认为无论如何有必要引入 UTF-8 BOM(因此其记事本应用程序可以检测 UTF-8),但由于 BOM 的顺序从不改变,因此不鼓励使用它。

至于unicode字符串,Python存储的是什么;实际上在 Python 3.3 中发生了变化。在 3.3 之前,在 C 级别内部,Python 存储 UTF16 或 UTF32 字节组合,这取决于 Python 是否使用宽字符支持编译(参见 How to find out if Python is compiled with UCS-2 or UCS-4?,UCS-2 本质上 UTF- 16 和 UCS-4 是 UTF-32)。因此,每个字符占用 2 或 4 个字节的内存。

从 Python 3.3 开始,内部表示使用表示字符串中所有字符所需的最小 字节数。对于纯 ASCII 和 Latin1 可编码文本,使用 1 个字节,用于 BMP 的其余部分使用 2 个字节,并使用包含超过 4 个字节的字符的文本。 Python 根据需要在格式之间切换。因此,在大多数情况下,存储变得更加高效。有关详细信息,请参阅 What's New in Python 3.3 .

我可以强烈建议您阅读 Unicode 和 Python:

关于 python 3 : Demystifying encode and decode methods,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13469591/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com