Python培训
400-996-5531
上一篇 Python 中的一些基础知识 对数据类型、变量做了一个简单的讲解,其中有个数据类型 - “字符串”,也就是文本。在计算机这个 0 和 1 的世界里面,若需要处理文本,那么就必须将其转化为数字才能处理。
然而如果让你用 0 和 1 来写一段代码,基本上是不可能事件。所以在计算机发明之初,歪果仁就将 127 个字母编码到计算机中,而这种编码也就被称之 ASCII(阿斯克)编码。比如 A 的编码就是 65
所以这篇文章将对计算机中的编码做一个讲解,以减少你在编写程序中经常遇到的一些编码问题。
好了,正题。。。
0x00、计算机中的单位
先解释几个计算机中的名词:
字(word)、字节(byte)、位(bit,比特)、字长(字的长度)1 字 = 2 字节(1 word = 2 byte)1 字节 = 8位 (1 byte = 8 bit)
一个字节的字长是 8,那么一个字的字长将是 16。其中 bit 是计算机中最小的单位,也就是我们说的 0 或者 1 这两个都是一个 bit 。这样算下来,一个字节也就是 8 个 0 或 1 来代表。
举个例子:
上面说过 A 这个字母也就是一个字节,由 8 个 bit组成的。因为其属于歪果仁定义好的 ASCII 编码中的一个字符,所以它被定义为 65,对应到 bit 上就是 01000001 ,而这 8 个 bit 也就是计算机熟悉的二进制数。通常情况下我们会使用十进制来表示一个数,你应该很少见人用二进制跟你说数字的,除非这个人傻了。那么二进制和十进制之间又是怎么转换的呢?
我们直接拿 65 这个十进制来说事:
我们平时会把这个数字读作:六十五,原因就是 65 = 6 x 10 + 5。那么 665 在十进制中就是: 6 x 10 的 2 次方 + 6 x 10 的 1次方 + 5 x 10的0 次方。所以你就可以看到十进制是每位的数字乘以 10 的 它所在位的次数。
那么,换成二进制 01000001 ,我们就可以猜到它的计算方式将是:
0 x 2 的 7次方 + 1 x 2 的 6 次方 + 0 x 2的5次方,一直加到 1 x 2 的 0 次方。加下来之后你就会发现它就变成一个十进制的数了。
当然若你需要将一个十进制转为二进制,那么一直除以2 的余数倒写,高位补 0 就好了:
65 的余数就是 1000001 ,那么我们倒着写,同时高位补零,就是 01000001。
关于计算机中的几个知识点,必须死记住。记不住就翻上去多看几遍。
0x01、字符编码
既然 ASCII 编码已经很“完美”的将字母和计算机内的数字联系了起来,那么我们是不是就能愉快的写任何文本内容了?
别忘了我们是中国人,我们用的是中文。中文在计算机肯定超出了 ASCII 编码中 127 个字母的范围,除非你在代码中一直用拼音代替中文,那么还可以规避这个问题,但你真的要是用拼音写的话,要是一个国内开发者看你代码会很容易误解,以为是另类的英语。
所以,对于中文超出 ASCII 编码的这种情况,后面就规定一个中文必须至少由两个字节来表示。对此,我们大中国就规定了一套新的编码,GB2312,用来把中文编进计算机。
然而全球又不止中文和英文这两种语言。全世界的语言有上百种,像日本就把日文编到 Shift_JIS 里,韩国就把韩文编到 Euc-kr 里。这样一来,各个国家都有了一套自己的编码,就会不可避免的出现冲突,结果就是,在多语言混合的文本中显示出来就会使乱码。
所以这时候就有一个牛逼的编码,Unicode,在时代的背景下它也不得不出现。Unicode 目的就是把所有语言都统一到一套编码里,这样也就不会再出现乱码的情况。
在 Unicode 中最普遍的就是使用两个字节来表示一个字符,也就是用 16 个 bit 来代表一个字符。
比如:字母 A 的 ASCII 编码的二进制是 01000001,那么用 Unicode 来表示 A 只要在高位增加一个字节,也就是 8 个 bit ,00000000。因此 A 的 Unicode 编码就是 0000000 01000001。
这时候问题就来了,如果一个文本全是用英文写的,那么在 Unicode 下将多出来 n 个 8 bit 的空间,也就是多了一倍的存储空间。在存储和传输上就非常不划算。
所以这时候又有一个新的编码,“可变长编码” UTF-8,之所以说它是变长的,是因为它将数字编码为 1-6 个字节,常用的英文字母被编码成 1 个字节,汉字通常是 3 个字节。所以,用 UTF-8 将会节省空间:
字符| ASCII | Unicode | UTF-8A|01000001 | 00000000 01000001 |01000001中|x|01001110 00101101|11100100 10111000 10101101
上面对 ASCII、Unicode、UTF-8 做了简单的描述,那么在计算机系统中它是怎么选择使用这些编码的呢:
在计算机内存中,会统一使用 Unicode 编码,然而当我们保存到硬盘或者需要传输的时候,就转化为 UTF-8 编码,一来节省了空间,二来也提高了传输效率。你在很多网页源码上也会看到:
0x02、Python 的字符串
那么搞清楚了计算机中的字符编码,这时候我们就需要回到 Python 中来。了解下 Python 对这些编码的支持。
在 Python 中有两个内置函数 ord 和 chr 这两个函数的意思是在 ASCII 码的前提下将字母和数字进行转换:
➜ /Users/xiyouMc > pythonPython 2.7.13 (default, Apr 4 2017, 08:47:57)[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.38)] on darwinType "help", "copyright", "credits" or "license" for more information.>>> ord('A')65>>> chr(65)'A'>>>
在Python 中用 Unicode 表示的字符串将是这样的:
>>> print(u'中文')中文>>> u'中'u'\u4e2d'>>>
可以看到是以 u 为开头的,同样的 u'中' 和 u'\u4e2d' 是一样的。
那么在 Python 如何在各种编码之间做灵活转化呢,这时候就得用到 encode 和 decode 这两个函数。
若你需要将 Unicode 编码转换为 UTF-8 或者其他编码,就需要用到 encode:
>>> u'中'.encode('gb2312')'\xd6\xd0'>>> u'中'.encode('utf-8')'\xe4\xb8\xad'>>>
当然,若你希望将其他编码的文本转化为 Unicode 编码,只需要用到 decode,并指明当前文本的编码格式:
>>> '\xe4\xb8\xad'.decode('utf-8')u'\u4e2d'
需要记住的一点是必须正确的指定编码格式,若指定错误将会抛出 Error 的异常,最常见的就是:
>>> '\xe4\xb8\xad'.decode('gb2312')Traceback (most recent call last): File "<stdin>", line 1, in <module>UnicodeDecodeError: 'gb2312' codec can't decode byte 0xad in position 2: incomplete multibyte sequence
由于 Python 源代码是一个文本文件,所以当你的源代码中包含中文的时候,就务必需要指明 utf-8 的编码在开头:
# -*- coding: utf-8 -*- print(u'中文')
关于 Python 2.x 和 3.x 有个明显的区别就是,在 2.x 上需要区分 'aa' 和 u'aa' ,前缀有 u 的就明确这是一个 Unicode 编码的文本。然后在 3.x 上已经把这两者统一为 Unicode 编码,也就可以不用再写 u 这个前缀。
这篇文章主要对初学者普及了下计算机内部使用的一些编码格式,同时对 Python 中的编码做了一个详细的讲解。若你在运行代码的时候遇到了 UnicodeDecodeError 这样的错误,那么一定是文本编码上有了一些问题。
本文内容转载自网络,本着分享与传播的原则,版权归原作者所有,如有侵权请联系我们进行删除!
填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved