tre*_*der 11 python unicode encoding python-3.x
假设我在Python中有一个字符串:
>>> s = 'python'
>>> len(s)
6
Run Code Online (Sandbox Code Playgroud)
现在我encode这个字符串是这样的:
>>> b = s.encode('utf-8')
>>> b16 = s.encode('utf-16')
>>> b32 = s.encode('utf-32')
Run Code Online (Sandbox Code Playgroud)
我从上述操作得到的是一个字节数组-即b,b16与b32只是字节阵列(每个字节是8位长的过程).
但我们编码了字符串.那么这是什么意思?我们如何将"编码"的概念与原始字节数组相连?
答案在于这些字节数组中的每一个都以特定方式生成.我们来看看这些数组:
>>> [hex(x) for x in b]
['0x70', '0x79', '0x74', '0x68', '0x6f', '0x6e']
>>> len(b)
6
Run Code Online (Sandbox Code Playgroud)
这个数组表明,对于每个字符,我们有一个字节(因为所有字符都低于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)
Run Code Online (Sandbox Code Playgroud)
在这里我们可以看到"编码到utf-16"首先将两个字节的BOM(FF FE)放入bytes数组中,然后,对于每个字符,它将两个字节放入数组中.(在我们的例子中,第二个字节始终为零)
>>> [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)
Run Code Online (Sandbox Code Playgroud)
在"utf-32编码"的情况下,我们首先放入BOM,然后为每个字符放置四个字节,最后我们将两个零字节放入数组中.
因此,我们可以说"编码过程"为字符串中的每个字符收集1 2或4个字节(取决于编码名称)并预先添加并向其附加更多字节以创建最终结果字节数组.
现在,我的问题:
b,b16并b32实际上是字节的列表.字符串的内存表示是什么?究竟是什么存储在内存中的字符串?encode(),每个字符的相应代码点被收集(代码点对应于编码名称)并放入一个或多个字节.我们做什么时到底发生了decode()什么?Mar*_*ers 18
首先,UTF-32是一个4字节编码,因此它的BOM也是一个四字节序列:
>>> import codecs
>>> codecs.BOM_UTF32
b'\xff\xfe\x00\x00'
Run Code Online (Sandbox Code Playgroud)
并且由于不同的计算机体系结构对字节顺序的处理方式不同(称为Endianess),因此BOM有两种变体:小端和大端:
>>> codecs.BOM_UTF32_LE
b'\xff\xfe\x00\x00'
>>> codecs.BOM_UTF32_BE
b'\x00\x00\xfe\xff'
Run Code Online (Sandbox Code Playgroud)
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'
Run Code Online (Sandbox Code Playgroud)
这取决于您的计算机体系结构,默认情况下使用哪一个.
UTF-8根本不需要BOM; UTF-8每个字符使用1个或多个字节(根据需要添加字节以编码更复杂的值),但这些字节的顺序在标准中定义.Microsoft认为有必要引入UTF-8 BOM(因此其Notepad应用程序可以检测到UTF-8),但由于BOM的顺序从不变化,因此不建议使用它.
至于Python为unicode字符串存储的内容; 在Python 3.3中实际发生了变化.在3.3之前,在C级内部,Python要么存储UTF16或UTF32字节组合,这取决于Python是否使用宽字符支持进行编译(请参阅如何找出Python是否使用UCS-2或UCS-4编译?, UCS-2 基本上是 UTF-16,UCS-4是UTF-32.因此,每个字符需要2或4个字节的内存.
从Python 3.3开始,内部表示使用表示字符串中所有字符所需的最小字节数.对于纯ASCII和Latin1可编码文本,使用1字节,因为使用了其余的BMP 2字节,并且使用包含超过该4字节的字符的文本.Python根据需要在格式之间切换.因此,对于大多数情况,存储变得更加有效.有关更多详细信息,请参阅Python 3.3中的新增功能.
我强烈建议你阅读Unicode和Python:
| 归档时间: |
|
| 查看次数: |
5828 次 |
| 最近记录: |