从历史中认识Python
前言
Python由吉多·范罗苏姆创造,第一版发布于1991年,它是ABC语言的后继者,也可以视之为一种使用传统中缀表达式的LISP方言。
一、Python 的起源
1989年的圣诞节,一个名叫吉多·范罗苏姆的荷兰程序员为了打发无聊的圣诞节假期,决定为他当时正在构思的一个新的脚本语言写一个解释器,它是ABC语言的后代,对UNIX / C程序员会有吸引力。这名程序员想到了他所喜爱的BBC电视剧——《蒙提·派森的飞行马戏团》(Monty Python’s Flying Circus),便选择了Python作为项目的标题。
二、了解作者
吉多·范罗苏姆(荷兰语:Guido van Rossum,1956年1月31日-),生于荷兰哈勒姆,计算机程序员,为Python程序设计语言的最初设计者及主要架构师。1986年在荷兰数学和计算机科学研究学会(CWI)工作时,吉多·范罗苏姆为BSD UNIX写了glob()子程序。吉多·范罗苏姆还参与帮助开发了ABC程序设计语言。在Python社区,吉多·范罗苏姆被人们认为是终身仁慈独裁者(BDFL),意思是他仍然关注Python的开发进程,并在必要的时刻做出决定。2018年7月12日,他宣布不再担任Python社区的BDFL。随后Python社区为了往后编程语言发展决策规划了领导委员会,吉多·范罗苏姆再度被选入成为五位委员会成员之一,持续贡献对于Python编程语言的发展决策。
三、大事件
1980年代,吉多·范罗苏姆开始了对 Python 的构思。
1989年,Python 已经有了雏形。
1991年2月,范罗苏姆在alt.sources上发布了最初代码(标记为版本0.9.0),这时就已经存在了带继承的类、异常处理、函数和核心数据类型list、dict、str等。在这个最初发行中就有了从Modula-3引进的模块系统,它的异常模型也类似于Modula-3,但增加了else子句。
1994年1月,Python 1.0发布。这个发行版主要新特征是包括了Amrit Prem提供的函数式编程工具lambda、map、filter和reduce。
1995年4月10号,Python 1.2发布。
1995年10月12号,Python 1.3发布。
1996年10月25号,Python 1.4增加了受Modula-3启发的关键字参数和对复数的内建支持,还包含采取名字修饰的一种基本形式的数据隐藏。
1997年12月31号,Python 1.5发布。
2000年9月5号,Python 1.6发布。
2000年10月16日,Python 2.0发布,介入了列表推导式,这是从函数式编程语言SETL和Haskell中引入的。它还向垃圾收集系统增加了环检测算法,并且支持Unicode。
2001年4月17日,Python 2.1发布,它支持了嵌套作用域,就像其他静态作用域语言一样。
2001年12月21日,Python 2.2发布,它的重大革新是将Python的类型(用C写成)和类(用Python写成)统一入一个层级,使得Python的对象模型成为纯粹和一致的面向对象的模型;还增加了迭代器,受CLU和Icon启发的生成器,和描述器协议。
2003年7月29日,Python 2.3发布。
2004年11月30日,Python 2.4发布,它加入了集合数据类型,和函数修饰器。
2006年12月19日,Python 2.5发布,它加入了with语句。
2008年10月1日,Python 2.6发布。
2010年7月3日,Python 2.7发布。
2008年12月3日,Python 3.0发布,它对语言做了较大修订而不能完全后向兼容。Python 3发行包括了2to3实用工具,它(至少部分的)自动将Python 2代码转换成Python 3代码。Python 3的很多新特性后来也被移植到旧的Python 2.6/2.7版本中。
2009年6月27日,Python 3.1发布,主要新增以下内容:
- 用C语言实现io模块。在3.0,io模块是用Python语言实现的,性能很慢,现在比3.0快了2~20倍。
- 新增OrderedDict类,能记住元素添加顺序的字典。举个用例:读取一个.ini文件,处理之后还能按原始顺序输出。
- 嵌套的with语句可以写在同一行。
- 更易懂的浮点数表示。由于浮点数在CPU内部的存在形式,repr(1.1)会显示为’1.1000000000000001’。现在显示为’1.1’,尽量确保eval(repr(f)) == f。
- 新增collections.Counter类,用于计数元素在序列中出现的次数。
- str.format()支持自动编号。
- format()和str.format()支持千分位分隔符。
- 新增tkinter.ttk模块。使tkinter控件呈现操作系统本地化风格,在windows下像windows,在mac下像mac,在linux下像linux。tkinter.ttk还包含了6个以前缺失的常用控件:Combobox, Notebook, Progressbar, Separator, Sizegrip, Treeview。
- round(x, n),如果x是整数,则返回一个整数。之前返回的是一个浮点数。
- itertools新增两个函数。
- 如果一个目录或一个zip文件里有__main__.py文件,把目录名或zip文件名传给Python解释器就可以启动程序。
- 新增importlib模块。把import的功能做成模块,并提供一些相关API。
- 64位版的int快了27%~55%。以前32位版、64位版int的计算单元都是15比特,现在64位版是30个比特。
- UTF-8、UTF-16、LATIN-1编码的decode速度是以前的2~4倍。
- json模块用C语言扩展,性能更快。
2011年2月20日,Python 3.2发布,主要新增以下内容:
- 新增argparse模块,解析命令行参数。用于替代功能有限的optparse模块。
- 新增concurrent.futures模块。定义了异步运行callable对象的接口(Future类),并提供了两个异步运行管理器:线程池、进程池。
- 标准库进行了大量改进。
- 增加html模块。在Python 3.2里,只有escape一个函数,用于转义html字符。
- 增加functools.lru_cache()装饰器,用于缓存函数的参数和返回值。以相同的参数再次调用函数时,不必再执行函数,直接返回缓存的返回值。
- itertools增加accumulate函数。累加(也可进行累减、累乘、累X等操作)。
- 字节串decode时支持’strict’和’ignore’错误处理,字符串encode时支持’strict’和’replace’错误处理。
- 优化表达式 x in {1, 2, 3}的性能。如果集合的元素都是常量,在编译时就会被放到一个frozenset里。
- 优化pickle模块。性能快了数倍。
- 优化list.sort()和sorted()。当使用key参数时,比以前快15%~40%。
- logging模块新增基于dict的配置方式,配置方式更灵活一些。
- WSGI版本更新到1.0.1。WSGI是Python程序和Web服务器之间的一种通用接口,1.0.1仅为Python3做了少量修改。
- 定义了一套稳定的ABI(二进制接口)。以前,每发布一个版本的Python,就要把第三方扩展重新编译一遍;现在提供了一套有限但稳定的ABI,很多情况下不必重新编译了。
- 改进.pyc文件的命名方式,以便区分不同版本Python生成的.pyc文件。
- 更新Unicode数据到6.0。
2012年9月29日,Python 3.3发布,主要新增以下内容:
- 新增yield from语法。
- 重新组织了操作系统相关异常的体系。更简化、有更好的粒度,并且基本上不必处理errno了。
- 新增lzma压缩模块,就是7-zip使用的压缩算法。
- 新增ipaddress模块,用于处理IPv4、IPv6的IP地址。
- 新增venv模块。用于创建虚拟环境,每个虚拟环境都能安装一套独立的第三方模块,可以更灵活的部署多个项目。
- 新增faulthandler模块。用于调试,能找出crash、超时、死锁等问题发生的位置。
- 新增unittest.mock模块。用于测试,可以模拟某个对象(类、实例、函数)的行为,从而方便测试。
- memoryview类的实现做了大量改进。memoryview可直接访问一个对象的内部数据(要求该对象支持Buffer Protocol协议),从而避免复制数据,当数据非常大时很有用。
- 用C语言重写了decimal模块,比以前快12倍(数据库操作)~120倍(高密度计算)。
- 随机hash。用一个随机数参与hash值的计算,这个随机数在启动python时生成。防止hash性能攻击。
- 字符串的内部存储更灵活。以前每个Unicode字符都占4字节,现在根据整个字符串的需要占1、2、4字节(日常使用的汉字基本上就用2个字节)。在一项Django测试中,内存使用比以前少了2~3倍。
- 新增Windows下的启动器,py.exe和pyw.exe。
- xml.etree.ElementTree默认使用C语言加速,以提高性能。
- utf-8编码快了2~4倍,utf-16编码的encode最多快了10倍。
- 增加可以共享key的字典。同一个类的多个实例,它们储存属性的字典现在可以共享key和hash了,当有大量实例时能节省内存。
- 增加python 2的字符串u修饰符:u’this is a string’。这个在python 3里没意义,仅仅是为了python 2程序迁移更方便。
- 更新Unicode数据到6.1。
2014年5月16日,Python 3.4发布。
- 集成了pip。用于安装、更新、卸载pypi上的第三方模块。
- 新增asyncio模块,关于协程的模块。这个模块提供了一个协程的事件循环器,以及一些具体工具。(线程、进程是互争资源,而协程是互让资源,主要用于异步处理并发I/O。协程是用生成器实现的。)
- 新增enum模块,提供枚举。好多人抱怨python没有枚举,现在有了,虽然是以模块的方式实现的。
- 新增pathlib模块,用面向对象的方式表示磁盘路径。简化路径操作,可以在Windows上处理linux路径、或反之。
- 新增statistics模块。提供了基本的统计功能,比如平均值、中位数、方差、标准差等。
- 新增selectors模块。基于已有的select模块,提供了一个更高级的接口。这两个模块用于IO复用模型(select、poll、epoll等)。
- 新增tracemalloc模块。一个调试工具,用于追踪、统计python的内存分配。
- html模块新增unescape函数。用于反转义html字符。
- functools模块新增singledispatch装饰器。用于定义单分派函数——传入不同类型的参数,函数可以有不同行为:
- pickle新增第4版协议。支持嵌套的类、巨大的对象、更多的类型,以及其它一些改进。但是直到python 3.6,pickle的默认协议还是第3版。
- 默认情况下,新创建文件的文件描述符不再允许被新进程(如子进程)使用。
- python解释器的启动快了30%。
- 改进str和bytes的hash算法,更能抵御DOS攻击。并且允许在编译CPython时更换别的hash算法。
- 允许在编译CPython时更换内存分配器。
- 启用Argument Clinic。在C语言写的底层函数被Python代码调用时,须要把参数解析成C语言的形式,使用Argument Clinic能更简便的生成参数解析代码。
- 更新Unicode数据到6.3。
2015年9月13日,Python 3.5发布。
- 为协程新增async和await语句,把协程的概念从生成器独立出来,并为之添加了async/await语句。增加“异步迭代器”,异步迭代器的aiter、anext函数是协程,可以将程序挂起。增加“异步上下文管理器”,异步上下文管理器的aenter、aexit函数是协程,可以将程序挂起。
- 新增矩阵乘法运算符@,如a @ b。
- 解包(unpacking)。*用于可迭代对象,**用于字典。
- 新增zipapp模块。把Python程序用Zip打包到一个可执行的.pyz文件。
- 允许bytes类型使用%格式化。
- 新增Type Hints和typing模块。方便(IDE等工具)静态分析代码,程序在实际运行时会忽略掉这些东西。
- bytes、bytearray、memoryview新增.hex()函数。
- math模块新增math.isclose()函数,判断两个数值是否相近,可以忽略浮点表示法带来的误差,另增加math.gcd()函数,计算最大公约数。
- 新增os.scandir()函数,更快、更省内存的遍历文件夹。在POSIX系统上比以前快35倍,在Windows系统上快720倍。os.walk()目前也在使用此函数。
- 用C语言重写了OrderedDict,快了4~100倍。
- functools.lru_cache()的大部分改用C语言实现,快了10~25倍。
- Windows版由VC2015编译,并且要求所有扩展也用VC2015编译。
- Python 3.5不再支持Windows XP及之前的系统,Python 3.4成了XP能用的最高版本。
- 提供Windows下的免安装绿色版,仅适合打包发布、不适合用于开发。在官网下载:Windows x86/x86-64 embeddable zip file。
- 不再使用.pyo文件名。-O和-OO选项不再生成xxx.pyo文件,而是分别生成xxx.opt-1.pyc和xxx.opt-2.pyc。
- 更新Unicode数据到8.0。
2016年12月23日,Python 3.6发布。
- 在f""修饰的字符串里直接使用变量。
- 在代码中,可以用下划线增加数值的可读性。
- 新增“异步生成器”。现在某些“异步迭代器”可以简化成“异步生成器”了。
- 新增“异步生成式”。在list、set、dict的生成式中,可以(通过async for)使用异步迭代器,也可以(通过await)调用协程。
- 新增secrets模块,生成强随机数。以前的random模块只能生成伪随机数,官方推荐在涉及安全问题时不再使用random模块。
- hashlib模块新增SHA-3算法。这个算法包括4个hash函数:SHA3-224、SHA3-256、SHA3-384、SHA3-512,输出是末尾数字指定的比特数;还包括2个扩展hash函数:SHAKE128、SHAKE256,输出是不大于128或256的任意比特数。
- 新增变量注释(Variable Annotations)。和Type Hints类似,用于(IDE等工具)静态分析代码。
- 更简便地自定义类的创建。有些情况下不必使用元类了。另给descriptor增加set_name方法。在创建descriptor所属的类时被调用,让descriptor可以感知被赋予的变量名。
- 普通的字典现在能记住元素的添加顺序。这不是Python的改动,仅是CPython的改动,因此官方并不鼓励用户依赖它的顺序。
- 得益于字典的顺序,3.6有两个改动:函数的参数**kwargs可以保留顺序,记住“类属性”的定义顺序,在以前,需要定义一个元类才能知道a、b、c的定义顺序。
- 现在,global和nolocal语句必须出现在实际使用该变量之前。不这样的话,在以前仅会给一个SyntaxWarning。
- 新增(文件系统)路径协议:如果一个对象有.fspath(self)函数、并且返回值是str或bytes类型,则说明这个对象能表示路径。同时增加os.fspath函数,与fspath配套使用。
- 给datetime.time和datetime.datetime的对象增加.fold属性。用于区分两个相同(但UTC不同)的当地时间,常见于夏令时结束的那天。如图,横轴是UTC时间,纵轴是当地时间:
- 在Windows操作系统上,CPython与控制台的通讯使用Unicode编码(CPython <-> utf-8 <-> utf-16-le <-> Windows操作系统),而不再使用当前的Code Page。好处是可以print、input所有Unicode字符(前提是字体也支持)。与此类似,CPython与Windows文件系统的通讯编码也从当前的Code Page改成Unicode了。
- 用C语言实现asyncio.Future类和asyncio.Task类,asyncio程序的性能快了25%~30%。
- glob模块的glob()函数和iglob()函数现在使用os.scandir()函数。快了3~6倍。
- pathlib.Path模块的glob()函数现在使用os.scandir()函数。快了1.5~4倍。
- 增加一个frame evaluation的C语言API,为第三方给CPython实现函数级JIT引擎提供了可能,IDE也可以用这个API实现性能更快的调试功能。
- 更新Unicode数据到9.0。Unicode 9.0支持西夏文字。
PS:Python 2.7的产品寿命结束日期最初设定为2015年,出于对大量的现存代码不能前向移植到Python 3的关切而延期至2020年。随着Python 2的产品寿命结束,只有Python 3.9和后续版本正在被完全支持,但仍提供对3.6、3.7和3.8版本的安全性修正。
在2020年12月,活跃的Python核心开发者选举Barry Warsaw、Brett Cannon、Carol Willing、Pablo Galindo Salgado和Thomas Wouters为2021年度“掌控委员会”的五位成员来领导这个项目。
总结
Python是一款非常有趣的语言,它简洁而又强大,有着极为广泛的应用。相信你一定听说过人生苦短,我用Python(Life is short, You need Python)这句话。目前人工智能越来越火,Python 凭借它扩展性强、第三方库丰富和免费开源等特点,在机器学习、数据挖掘、人工智能等领域有着很大优势,前景非常值得期待。接下来,让我们一起玩转Python吧!
上一节:
下一节: