字节字符串与 Unicode 字符串。 Python
Posted
技术标签:
【中文标题】字节字符串与 Unicode 字符串。 Python【英文标题】:byte string vs. unicode string. Python 【发布时间】:2012-04-21 01:41:44 【问题描述】:能否详细解释一下Python中字节字符串和Unicode字符串的区别。我已阅读this:
字节码只是将源代码转换成字节数组
这是否意味着 Python 有自己的编码/编码格式?还是使用操作系统设置? 我不明白。你能解释一下吗? 谢谢!
【问题讨论】:
coolinterview.com 看起来像是一个糟糕的信息来源。我不会依赖它。 “字节码”通常指完全不同的东西,docs.python.org/glossary.html“Python 源代码被编译成字节码,是 CPython 解释器中 Python 程序的内部表示。字节码也缓存在 . pyc 和 .pyo 文件” +1 dbr 的评论。字节码是与 Unicode 无关的内部 CPython 实现细节,您可能不必担心。 【参考方案1】:没有python不使用自己的编码。它将使用它有权访问和您指定的任何编码。 str
中的一个字符代表一个 unicode 字符。但是,要表示超过 256 个字符,单独的 unicode 编码每个字符使用一个以上的字节来表示许多字符。 bytearray
对象使您可以访问底层字节。 str
对象具有 encode
方法,该方法接受一个表示编码的字符串并返回表示该编码中的字符串的 bytearray
对象。 bytearray
对象具有decode
方法,该方法接受一个表示编码的字符串并返回str
,该str
将bytearray
解释为以给定编码编码的字符串。这是一个例子。
>>> a = "αά".encode('utf-8')
>>> a
b'\xce\xb1\xce\xac'
>>> a.decode('utf-8')
'αά'
我们可以看到 UTF-8 使用了四个字节,\xce、\xb1、\xce 和 \xac 来表示两个字符。在 Ignacio Vazquez-Abrams 提到的 Spolsky 文章之后,我会阅读 Python Unicode Howto。
【讨论】:
你的意思是bytes
对象,不是bytearray
:事实上,type("é".encode('UTF-8'))
是bytes
,而不是bytearray
。
哪个 Python 版本? 2.7 报告为<type 'str'>
。
这东西真的很混乱。我从来没有真正理解 Python 字符串
它是 python 3,如果我们在每个字符串类型上键入 help() 就会给出一个清晰的概念。
Ignacio Vazquez-Abrams 删除了他的答案,但 Joel Spolsky Unicode 文章是 here。对 tbat 答案的评论提到了 Ned Batchelder 的 Unipain,这与 Python 2 尤其相关。【参考方案2】:
这是一个仅适用于 Python 3 的简单解释的尝试。我希望来自外行,这将有助于为完全外行的人消除一些困惑。如果有任何技术上的不准确之处,请原谅我并随时指出。
假设您以通常的方式使用 Python 3 创建一个字符串:
stringobject = 'ant'
stringobject
将是一个 unicode 字符串。
unicode 字符串由 unicode 字符组成。在上面的stringobject
中,unicode 字符是单个字母,例如a, n, t
每个 unicode 字符都分配有一个代码点,该代码点可以表示为一系列十六进制数字(一个十六进制数字可以取 16 个值,范围从 0-9 和 A-F)。例如,字母'a'
等价于'\u0061'
,'ant' 等价于'\u0061\u006E\u0074'
。
所以你会发现,如果你输入,
stringobject = '\u0061\u006E\u0074'
stringobject
您还将获得输出'ant'
。
现在,unicode 被转换为字节,在一个称为 encoding 的过程中。 将字节转换为 unicode 的逆过程称为解码。
这是怎么做到的?由于每个十六进制数字可以取 16 个不同的值,因此可以体现为 4 位二进制序列(例如十六进制数字 0 可以二进制表示为 0000,十六进制数字 1 可以表示为 0001 等等)。如果一个 unicode 字符的代码点由四个十六进制数字组成,则需要一个 16 位二进制序列来对其进行编码。
不同的编码系统为将 unicode 转换为位指定了不同的规则。最重要的是,编码用于表示每个 unicode 字符的位数不同。
例如,ASCII 编码系统每个字符仅使用 8 位(1 个字节)。因此,它只能对 unicode 字符进行编码,其代码点最长为两个十六进制数字(即 256 个不同的 unicode 字符)。 UTF-8 编码系统每个字符使用 8 到 32 位(1 到 4 个字节),因此它可以对 unicode 字符进行编码,其代码点最长为 8 个十六进制数字,即一切。
运行以下代码:
byteobject = stringobject.encode('utf-8')
byteobject, type(byteobject)
使用 utf-8 编码系统将 unicode 字符串转换为字节字符串,并返回 b'ant', bytes'
。
请注意,如果您使用 'ASCII' 作为编码系统,则不会遇到任何问题,因为 'ant' 中的所有代码点都可以用 1 个字节表示。但如果你有一个 unicode 字符串,其中包含的字符的代码点长于两个十六进制数字,你会得到一个 UnicodeEncodeError
。
同样,
stringobject = byteobject.decode('utf-8')
stringobject, type(stringobject)
给你'ant', str
。
【讨论】:
(1) 一般来说,一个用户感知的字符,例如g̈
,可能对应于几个Unicode代码点(在这种情况下为U+0067 U+0308)。 (2) Unicode 代码点的编码可能与其编号无关,即 8 位编码可能表示 ~0x100 个字符,所有这些字符不必连续(没有必要“一个由四个十六进制数字组成的代码点,它需要一个 16 位二进制序列来对其进行编码”——谈论对单个代码点进行编码所需的大小是没有意义的-- 只有一组字符有限制)
ASCII 是 7 位编码,而不是 8 位。试试,例如chr(128).encode('ascii')
,你会得到一个编码错误。以上是关于字节字符串与 Unicode 字符串。 Python的主要内容,如果未能解决你的问题,请参考以下文章