搜索
首页系统教程LINUXPython 编程的历史演变

Python 编程的历史演变

Jan 01, 2024 am 09:31 AM
linuxlinux教程红帽linux系统linux命令linux认证红帽linuxlinux视频

导读 一旦走上了编程之路,如果你不把编码问题搞清楚,那么它将像幽灵一般纠缠你整个职业生涯,各种灵异事件会接踵而来,挥之不去。只有充分发挥程序员死磕到底的精神你才有可能彻底摆脱编码问题带来的烦恼。

我第一次遇到编码问题是写 JavaWeb 相关的项目,一串字符从浏览器游离到应用程序代码中,翻江倒海沉浸到数据库中,随时随地都有可能踩到编码的地雷。第二次遇到编码问题就是学 Python 的时候,在爬取网页数据时,编码问题又出现了,当时我的心情是崩溃的,用时下最ing的一句话就是:“我当时就懵逼了”。

为了搞清字符编码,我们得从计算机的起源开始,计算机中的所有数据,不论是文字、图片、视频、还是音频文件,本质上最终都是按照类似 01010101 的数字形式存储的。我们是幸运的,我们也是不幸的,幸运的是时代赋予了我们都有机会接触计算机,不幸的是,计算机不是我们国人发明的,所以计算机的标准得按美帝国人的习惯来设计,那么最开始计算机是通过什么样的方式来表现字符的呢?这要从计算机编码的发展史说起。

ASCII

每个做 JavaWeb 开发的新手都会遇到乱码问题,每个做 Python 爬虫的新手都会遇到编码问题,为什么编码问题那么蛋疼呢?这个问题要从1992年 Guido van Rossum 创造 Python 这门语言说起,那时的 Guido 绝对没想到的是 Python 这门语言在今天会如此受大家欢迎,也不会想到计算机发展速度会如此惊人。Guido 在当初设计这门语言时是不需要关心编码的,因为在英语世界里,字符的个数非常有限,26个字母(大小写)、10个数字、标点符号、控制符,也就是键盘上所有的键所对应的字符加起来也不过是一百多个字符而已。这在计算机中用一个字节的存储空间来表示一个字符是绰绰有余的,因为一个字节相当于8个比特位,8个比特位可以表示256个符号。于是聪明的美国人就制定了一套字符编码的标准叫 ASCII(American Standard Code for Information Interchange),每个字符都对应唯一的一个数字,比如字符 A 对应的二进制数值是 01000001,对应的十进制就是 65。最开始 ASCII 只定义了 128 个字符编码,包括 96 个文字和 32 个控制符号,一共 128 个字符,只需要一个字节的 7 位就能表示所有的字符,因此 ASCII 只使用了一个字节的后7位,最高位都为 0。
Python 编码的前世今生

EASCII (ISO/8859-1)

然而计算机慢慢地普及到其他西欧地区时,他们发现还有很多西欧所特有的字符是 ASCII 编码表中没有的,于是后来出现了可扩展的 ASCII 叫 EASCII ,顾名思义,它是在 ASCII 的基础上扩展而来,把原来的 7 位扩充到 8 位,它完全兼容 ASCII,扩展出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。然而 EASCII 时代是一个混乱的时代,大家没有统一标准,他们各自把最高位按照自己的标准实现了自己的一套字符编码标准,比较著名的就有 CP437, CP437 是 Windows 系统中使用的字符编码,如下图:
Python 编码的前世今生
另外一种被广泛使用的 EASCII 还有 ISO/8859-1(Latin-1),它是国际标准化组织(ISO)及国际电工委员会(IEC)联合制定的一系列8位元字符集的标准,ISO/8859-1 只继承了 CP437 字符编码的 128-159 之间的字符,所以它是从 160 开始定义的,不幸的是这些众多的 ASCII 扩充字集之间互不兼容。
Python 编码的前世今生

GBK

随着时代的进步,计算机开始普及到千家万户,比尔盖茨让每个人桌面都有一台电脑的梦想得以实现。但是计算机进入中国不得不面临的一个问题就是字符编码,虽然咱们国家的汉字是人类使用频率最多的文字,汉字博大精深,常见的汉字就有成千上万,这已经大大超出了 ASCII 编码所能表示的字符范围了,即使是 EASCII 也显得杯水车薪,于是聪明的中国人自己弄了一套编码叫 GB2312,又称GB0,1981由中国国家标准总局发布。GB2312 编码共收录了6763个汉字,同时它还兼容 ASCII。GB2312 的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆 99.75% 的使用频率。不过 GB2312 还是不能 100% 满足中国汉字的需求,对一些罕见的字和繁体字 GB2312 没法处理,后来就在 GB2312 的基础上创建了一种叫 GBK 的编码。GBK 不仅收录了 27484 个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。同样 GBK 也是兼容 ASCII 编码的,对于英文字符用 1 个字节来表示,汉字用两个字节来标识。

Unicode

对于如何处理中国人自己的文字我们可以另立山头,按照我们自己的需求制定一套编码规范,但是计算机不止是美国人和中国人用啊,还有欧洲、亚洲其他国家的文字诸如日文、韩文全世界各地的文字加起来估计也有好几十万,这已经大大超出了 ASCII 码甚至 GBK 所能表示的范围了,况且人家为什么用采用你 GBK 标准呢?如此庞大的字符库究竟用什么方式来表示好呢?于是统一联盟国际组织提出了 Unicode 编码,Unicode 的学名是“Universal Multiple-Octet Coded Character Set”,简称为UCS。
Python 编码的前世今生
Unicode 有两种格式:UCS-2 和 UCS-4。UCS-2 就是用两个字节编码,一共 16 个比特位,这样理论上最多可以表示 65536个字符,不过要表示全世界所有的字符显然 65536 个数字还远远不够,因为光汉字就有近 10 万个,因此 Unicode 4.0 规范定义了一组附加的字符编码,UCS-4 就是用 4 个字节(实际上只用了 31 位,最高位必须为 0)。
Unicode 理论上完全可以涵盖一切语言所用的符号。世界上任何一个字符都可以用一个 Unicode 编码来表示,一旦字符的 Unicode 编码确定下来后,就不会再改变了。但是 Unicode 有一定的局限性,一个 Unicode 字符在网络上传输或者最终存储起来的时候,并不见得每个字符都需要两个字节,比如一字符“ A “,用一个字节就可以表示的字符,偏偏还要用两个字节,显然太浪费空间了。第二问题是,一个 Unicode 字符保存到计算机里面时就是一串 01 数字,那么计算机怎么知道一个 2 字节的 Unicode 字符是表示一个 2 字节的字符呢,还是表示两个 1 字节的字符呢,如果你不事先告诉计算机,那么计算机也会懵逼了。Unicode 只是规定如何编码,并没有规定如何传输、保存这个编码。例如 “汉” 字的 Unicode 编码是 6C49,我可以用 4 个 ASCII 数字来传输、保存这个编码;也可以用 UTF-8 编码的 3 个连续的字节 E6 B1 89 来表示它。关键在于通信双方都要认可。因此 Unicode 编码有不同的实现方式,比如:UTF-8、UTF-16 等等。这里的 Unicode 就像英语一样,做为国与国之间交流世界通用的标准,每个国家有自己的语言,他们把标准的英文文档翻译成自己国家的文字,这是实现方式,就像 UTF-8。

UTF-8

UTF-8(Unicode Transformation Format)作为 Unicode 的一种实现方式,广泛应用于互联网,它是一种变长的字符编码,可以根据具体情况用 1-4 个字节来表示一个字符。比如英文字符这些原本就可以用 ASCII 码表示的字符用 UTF-8 表示时就只需要一个字节的空间,和 ASCII 是一样的。对于多字节(n 个字节)的字符,第一个字节的前 n 为都设为 1,第 n+1 位设为 0,后面字节的前两位都设为 10。剩下的二进制位全部用该字符的 UNICODE 码填充。
Python 编码的前世今生
以汉字“好”为例,“好”对应的 Unicode 是 597D,对应的区间是 0000 0800 -- 0000 FFFF,因此它用 UTF-8 表示时需要用 3 个字节来存储,597D 用二进制表示是: 0101100101111101 ,填充到 1110xxxx 10xxxxxx 10xxxxxx 得到11100101 10100101 10111101,转换成 16 进制:E5A5BD ,因此“好”的 Unicode “597D”对应的 UTF-8 编码是“E5A5BD”。

中文 好
unicode 0101 100101 111101
编码规则 1110xxxx 10xxxxxx 10xxxxxx
--------------------------
utf-8 11100101 10100101 10111101
--------------------------
16进制utf-8 e 5 a 5 b d Python 字符编码

现在总算把理论说完了。再来说说 Python 中的编码问题。Python 的诞生时间比 Unicode 要早很多,Python 的默认编码是ASCII。
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
所以在 Python 源代码文件中如果不显式地指定编码的话,将出现语法错误

#test.py

print "你好"
上面是 test.py 脚本,运行

python test.py

就会包如下错误:

File “test.py”, line 1 yntaxError: Non-ASCII character ‘/xe4′ in file test.py on line 1, but no encoding declared;

为了在源代码中支持非 ASCII 字符,必须在源文件的第一行或者第二行显示地指定编码格式:

# coding=utf-8

或者是:

#!/usr/bin/python
# -*- coding: utf-8 -*-

在 Python 中和字符串相关的数据类型,分别是 str、unicode 两种,他们都是 basestring 的子类,可见 str 与 unicode 是两种不同类型的字符串对象。

    basestring
      /  / 
     /    /
   str    unicode

对于同一个汉字“好”,用 str 表示时,它对应的就是 UTF-8 编码'/xe5/xa5/xbd',而用 Unicode 表示时,它对应的符号就是u'/u597d',与u "好"是等同的。需要补充一点的是,str 类型的字符其具体的编码格式是 UTF-8 还是 GBK,还是其它格式,根据操作系统相关。比如在 Windows 系统中,cmd 命令行中显示的:

# windows终端
>>> a = '好'
>>> type(a)
<type>
>>> a
'/xba/xc3'
</type>

而在 Linux 系统的命令行中显示的是:

# linux终端
>>> a='好'
>>> type(a)
<type>
>>> a
'/xe5/xa5/xbd'

>>> b=u'好'
>>> type(b)
<type>
>>> b
u'/u597d'
</type></type>

不论是 Python3x、Java 还是其他编程语言,Unicode 编码都成为了语言的默认编码格式,而数据最后保存到介质中的时候,不同的介质可有用不同的方式,有些人喜欢用 UTF-8,有些人喜欢用 GBK,这都无所谓,只要平台统一的编码规范,具体怎么实现并不关心。

Python 编码的前世今生

str 与 unicode 的转换

那么在 Python 中 str 和 unicode 之间是如何转换的呢?这两种类型的字符串类型之间的转换就是靠这两个方法:decode 和encode。

Python 编码的前世今生

#从str类型转换到unicode
s.decode(encoding)   =====>  <type> to <type>
#从unicode转换到str
u.encode(encoding)   =====>  <type> to <type>

>>> c = b.encode('utf-8')
>>> type(c)
<type>
>>> c
'/xe5/xa5/xbd'

>>> d = c.decode('utf-8')
>>> type(d)
<type>
>>> d
u'/u597d'
</type></type></type></type></type></type>

这个'/xe5/xa5/xbd'就是 Unicode u'好'通过函数 encode 编码得到的 UTF-8 编码的 str 类型的字符串。反之亦然,str 类型的 c 通过函数 decode 解码成 Unicode 字符串 d。

str(s) 与 unicode(s)

str(s) 和 unicode(s) 是两个工厂方法,分别返回 str 字符串对象和 Unicode 字符串对象,str(s) 是 s.encode(‘ascii’) 的简写。实验:

>>> s3 = u"你好"
>>> s3
u'/u4f60/u597d'
>>> str(s3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)</module></stdin>

上面 s3 是 Unicode 类型的字符串,str(s3)相当于是执行 s3.encode(‘ascii’),因为“你好”两个汉字不能用 ASCII 码来表示,所以就报错了,指定正确的编码:s3.encode('gbk') 或者 s3.encode('utf-8') 就不会出现这个问题了。类似的 Unicode 有同样的错误:

>>> s4 = "你好"
>>> unicode(s4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)
>>></module></stdin>

unicode(s4)等效于s4.decode('ascii')
,因此要正确的转换就要正确指定其编码 s4.decode('gbk') 或者s4.decode('utf-8')。

乱码

所有出现乱码的原因都可以归结为字符经过不同编码解码在编码的过程中使用的编码格式不一致,比如:

# encoding: utf-8

>>> a='好'
>>> a
'/xe5/xa5/xbd'
>>> b=a.decode("utf-8")
>>> b
u'/u597d'
>>> c=b.encode("gbk")
>>> c
'/xba/xc3'
>>> print c

UTF-8 编码的字符‘’占用 3 个字节,解码成 Unicode 后,如果再用 GBK 来解码后,只有 2 个字节的长度了,最后出现了乱码的问题,因此防止乱码的最好方式就是始终坚持使用同一种编码格式对字符进行编码和解码操作。

Python 编码的前世今生

其他技巧

对于如 Unicode 形式的字符串(str 类型):

s = 'id/u003d215903184/u0026index/u003d0/u0026st/u003d52/u0026sid'

转换成真正的 Unicode 需要使用:

s.decode('unicode-escape')

测试:

>>> s = 'id/u003d215903184/u0026index/u003d0/u0026st/u003d52/u0026sid/u003d95000/u0026i'
>>> print(type(s))
<type>
>>> s = s.decode('unicode-escape')
>>> s
u'id=215903184&index=0&st=52&sid=95000&i'
>>> print(type(s))
<type>
>>>
</type></type>

以上代码和概念都是基于 Python2.x。

以上是Python 编程的历史演变的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:Linux就该这么学。如有侵权,请联系admin@php.cn删除
很难学习Linux吗?很难学习Linux吗?Apr 18, 2025 am 12:23 AM

学习Linux并不难。1.Linux是一个开源操作系统,基于Unix,广泛应用于服务器、嵌入式系统和个人电脑。2.理解文件系统和权限管理是关键,文件系统是层次化的,权限包括读、写和执行。3.包管理系统如apt和dnf使得软件管理方便。4.进程管理通过ps和top命令实现。5.从基本命令如mkdir、cd、touch和nano开始学习,再尝试高级用法如shell脚本和文本处理。6.常见错误如权限问题可以通过sudo和chmod解决。7.性能优化建议包括使用htop监控资源、清理不必要文件和使用sy

Linux管理员的薪水是多少?Linux管理员的薪水是多少?Apr 17, 2025 am 12:24 AM

Linux管理员的平均年薪在美国为75,000至95,000美元,欧洲为40,000至60,000欧元。提升薪资可以通过:1.持续学习新技术,如云计算和容器技术;2.积累项目经验并建立Portfolio;3.建立职业网络,拓展人脉。

Linux的主要目的是什么?Linux的主要目的是什么?Apr 16, 2025 am 12:19 AM

Linux的主要用途包括:1.服务器操作系统,2.嵌入式系统,3.桌面操作系统,4.开发和测试环境。Linux在这些领域表现出色,提供了稳定性、安全性和高效的开发工具。

互联网在Linux上运行吗?互联网在Linux上运行吗?Apr 14, 2025 am 12:03 AM

互联网运行不依赖单一操作系统,但Linux在其中扮演重要角色。Linux广泛应用于服务器和网络设备,因其稳定性、安全性和可扩展性受欢迎。

Linux操作是什么?Linux操作是什么?Apr 13, 2025 am 12:20 AM

Linux操作系统的核心是其命令行界面,通过命令行可以执行各种操作。1.文件和目录操作使用ls、cd、mkdir、rm等命令管理文件和目录。2.用户和权限管理通过useradd、passwd、chmod等命令确保系统安全和资源分配。3.进程管理使用ps、kill等命令监控和控制系统进程。4.网络操作包括ping、ifconfig、ssh等命令配置和管理网络连接。5.系统监控和维护通过top、df、du等命令了解系统运行状态和资源使用情况。

使用Linux别名提高自定义命令快捷方式的生产率使用Linux别名提高自定义命令快捷方式的生产率Apr 12, 2025 am 11:43 AM

介绍 Linux是一个强大的操作系统,由于其灵活性和效率,开发人员,系统管理员和电源用户都喜欢。但是,经常使用长而复杂的命令可能是乏味的

Linux实际上有什么好处?Linux实际上有什么好处?Apr 12, 2025 am 12:20 AM

Linux适用于服务器、开发环境和嵌入式系统。1.作为服务器操作系统,Linux稳定高效,常用于部署高并发应用。2.作为开发环境,Linux提供高效的命令行工具和包管理系统,提升开发效率。3.在嵌入式系统中,Linux轻量且可定制,适合资源有限的环境。

在Linux上掌握道德黑客的基本工具和框架在Linux上掌握道德黑客的基本工具和框架Apr 11, 2025 am 09:11 AM

简介:通过基于Linux的道德黑客攻击数字边界 在我们越来越相互联系的世界中,网络安全至关重要。 道德黑客入侵和渗透测试对于主动识别和减轻脆弱性至关重要

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具