字节串 vs. Unicode 字符串。Python

43
你能详细解释一下Python中字节字符串和Unicode字符串的区别吗?我已经阅读了this

字节码只是将源代码转换为字节数组

这是否意味着Python有自己的编码格式?还是它使用操作系统设置?我不理解,请你解释一下,谢谢!

13
coolinterview.com看起来是一个糟糕的信息来源,我不会依赖它。 - bames53
8
“字节码”通常指的是完全不同的东西。 在http://docs.python.org/glossary.html中,“Python源代码被编译成字节码,这是CPython解释器中Python程序的内部表示。 字节码还会在.pyc和.pyo文件中缓存”。 - dbr
+1 dbr的评论。 字节码是内部CPython实现细节,与Unicode无关,您可能不必担心它。 - bobince
2个回答

40

不,Python没有使用自己的编码方式 - 它将使用任何它可以访问和你指定的编码方式。

str中的一个字符代表一个Unicode字符。然而,为了表示超过256个字符,单个Unicode编码需要用多于一个字节的字符来表示许多字符。

bytes对象让你访问底层字节。str对象有一个encode方法,它接受一个字符串表示的编码方式,并返回代表该编码方式下该字符串的bytes对象。 bytes对象有一个decode方法,它接受一个字符串表示的编码方式,并返回解释该byte作为以给定编码方式编码的字符串所得到的str

例如:

>>> a = "αά".encode('utf-8')
>>> a
b'\xce\xb1\xce\xac'
>>> a.decode('utf-8')
'αά'
我们可以看到UTF-8使用四个字节,\xce\xb1\xce\xac来表示两个字符。
相关阅读:

35

这里是一份简单易懂的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会被转换为字节,这个过程称为编码。将字节转换回Unicode的反向过程称为解码。
这是如何完成的呢?由于每个十六进制数字可以有16种不同的值,因此它可以用一个4位二进制序列来表示(例如,十六进制数字0可以表示为0000的二进制数,十六进制数字1可以表示为0001的二进制数,依此类推)。如果一个Unicode字符具有由四个十六进制数字组成的代码点,则需要一个16位二进制序列来对其进行编码。
不同的编码系统规定了将Unicode转换为位的不同规则。最重要的是,编码在用于表示每个Unicode字符的位数上有所不同。
例如,ASCII编码系统每个字符仅使用8位(1字节)。因此,它只能编码长度为两个十六进制数字的代码点的Unicode字符(即256个不同的Unicode字符)。UTF-8编码系统每个字符使用8到32位(1到4字节),因此它可以编码长度为8个十六进制数字的代码点的Unicode字符,即所有字符。
运行以下代码:
byteobject = stringobject.encode('utf-8')
byteobject, type(byteobject)

将Unicode字符串使用UTF-8编码系统转换为字节串,并返回b'ant', bytes'

请注意,如果您使用“ASCII”作为编码系统,您不会遇到任何问题,因为“ant”中的所有代码点都可以用1个字节表示。但是,如果您有一个包含比两个十六进制数字更长的代码点的Unicode字符串,您将会得到一个UnicodeEncodeError

同样地,

stringobject = byteobject.decode('utf-8')
stringobject, type(stringobject)

这个函数给你'ant', str


2
(1) 一般来说,用户感知的字符,例如 可能对应于多个 Unicode 码点(在这种情况下为 U+0067 U+0308)。 (2) Unicode 码点的编码可能与其编号无关,即 8 位编码可以表示约 0x100 个字符,不必要求所有这些字符都必须是连续的(一个由四个十六进制数字组成的码点需要一个 16 位二进制序列来编码它并不合理——只有一组字符会施加限制)。 - jfs
1
ASCII是一种7位编码,而不是8位。尝试使用chr(128).encode('ascii'),你会得到一个编码错误。 - PM 2Ring

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接