更多课程 选择中心


Python培训

400-111-8989

Python 中应该注意的编码问题

  • 发布: 马超
  • 来源:DeveloperPython
  • 时间:2017-10-27 16:47

上一篇 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 这样的错误,那么一定是文本编码上有了一些问题。

本文内容转载自网络,本着分享与传播的原则,版权归原作者所有,如有侵权请联系我们进行删除!

预约申请免费试听课

填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:入门学习python的五步曲
下一篇:Python教学:编程如何培养学生计算思维

2021年Python全套免费视频教程在哪里?

Python编程学习路线

Python最高有几级?

人工智能与语音遥控的区别?

  • 扫码领取资料

    回复关键字:视频资料

    免费领取 达内课程视频学习资料

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省