字节字符串与 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,该strbytearray 解释为以给定编码编码的字符串。这是一个例子。

>>> 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) 一般来说,一个用户感知的字符,例如,可能对应于几个Unicode代码点(在这种情况下为U+0067 U+0308)。 (2) Unicode 代码点的编码可能与其编号无关,即 8 位编码可能表示 ~0x100 个字符,所有这些字符不必连续(没有必要“一个由四个十六进制数字组成的代码点,它需要一个 16 位二进制序列来对其进行编码”——谈论对单个代码点进行编码所需的大小是没有意义的-- 只有一组字符有限制) ASCII 是 7 位编码,而不是 8 位。试试,例如chr(128).encode('ascii'),你会得到一个编码错误。

以上是关于字节字符串与 Unicode 字符串。 Python的主要内容,如果未能解决你的问题,请参考以下文章

UNICODE与ANSI的区别

unicode和多字节字符集的区别

VS2010与VS2013中的多字节编码与Unicode编码问题

Django之Form组件与验证规则

js实现unicode码字符串与utf8字节数据互转

UTF-8与GBK字符集解析