由于Python3编码方面的内容变化很多,所以重新写一篇文章来讨论一下。也当成自己学习的记录了。
编码?你需要知道的那些事:3-Python2.x为什么有乱码
更新
The rules for translating a Unicode string into a sequence of bytes are called an encoding.
Unicode字符串转换成字节序列的规则被称为编码。
之前的文章里面提到过,Python2.x默认的编码是ascii(因为当初Python诞生的时候,还没有Unicode,具体的看之前文章),这也是为什么我们讨论在Python2.x中出现乱码的情况。
1. 默认编码变化
在Python3中,默认编码变为了utf-8,我们可以进行验证。
|
|
这样我们在使用print函数、读取文件、保存文件时,Python3默认都会使用utf-8进行编码。
下面做一个测试。
这是一个使用GB 18030(也是一类GBK编码标准,主要是增加了汉字数量)编码保存的文件,我们在Python中使用默认方式打开会出现什么结果呢?
都不让打开,直接报错,肯定的毕竟UTF-8和GBK不兼容。正确方式如下:
|
|
看来,是和GBK说再见的时候了(尽量少用),如果都使用默认编码的话一般不会再出现乱码问题了。
下面介绍utf-8编码的规则和好处。
-
utf-8进行编码的规则:
- 如果Unicode码位(编号)< 128,则由相应的字节值表示。
- 如果Unicode码位(编号)> = 128,将它变成两个,三个或四个字节的序列,其中序列的每个字节都在128到255之间。
-
使用utf-8进行编码的好处(半翻译):
-
它可以处理任意Unicode码位(编号)。
-
将一个Unicode字符串变成一个不包含嵌入零字节的字节序列。
-
一串ASCII文本也是有效的UTF-8文本(具有兼容性)。
-
UTF-8相当紧凑,大多数常用字符可以用一个或两个字节表示(节省内存)。
-
如果字节损坏或丢失,可以确定下一个UTF-8编码代码点的开始并重新同步。
-
2. str与bytes
Python2.x中,字符串有两种表现类型:一个是Unicode(表示文本字符串)、一个是str(表示字节序列)。
在Python3.x中,使用str表示字符串,bytes表示字节序列。官方文档是这样介绍的:
-
str (字符)
Strings are immutable sequences of Unicode code points.
str是一串不可变的Unicode码位(编码)序列。
-
bytes(字节)
bytes is an immutable sequence of integers in the range
0 <= x < 256
.bytes是一串不可变的整数(0 <= x < 256)序列。
下面这张图可以一定程度上说明区别。
现在我们定义一个str字符,它默认就是一个Unicode的字符。
|
|
上面输出的10003(十六进制表示为0x2713)正是对钩字符在Unicode中的编号(码位)。
现在我们使用utf-8编码将字符编码为字节:
|
|
可以看出✓字符使用utf-8编码后是三个字节,如果使用GBK进行编码呢?
|
|
我x,怎么出错了? 不会啊,思路没有错啊,将Unicode的字符编码为字节呢。 其实,不出错才不正常呢,因为GBK字符集中没有这个字符。
如果我们知道了一个字符的Unicode编号,怎么将它变为字符呢?好问题。
比如有一个粗实心心。它的编号(码位)是10084,我们使用下面代码将它变为一个字符(注意:GBK中没有这个字符)。
|
|
下面是上面使用到的两个函数的原型:
-
ord(c)
Given a string representing one Unicode character, return an integer representing the Unicode code point of that character.
-
chr
(i)Return the string representing a character whose Unicode code point is the integer i.