18
5 月
从0开始的Python教程01:Python又是什么?
- By IanGoo
Python近几年顶着机器学习的风口颇有些红得发紫的意思——因为目前几个知名度颇高的深度学习框架基本上都是基于Python的,包括已经出圈的AlphaGo,这使得很多并不是很了解计算机的吃瓜群众都听说过Python这门“技术”。
由于Python最近才走入大众视野,而且又和深度学习这样的前沿技术挂上了钩,以至于很多人认为Python非常年轻,其实并不是。Python其实诞生于1989年,发布于1990年。相比之下,1995年的Java、1997年的C++、2001年的C#这些经常被误认为比Python资格还老的语言其实都是小辈。

Python的发明者是荷兰人Guido van Rossum。据他本人说,Python本来只是一个小玩意儿,是在1989年的圣诞节假期他利用业余时间写着玩的。Python的本意是蟒蛇,Logo也是一蓝一黄两条蛇,不过Rossum想到这个名字并不是因为蛇,而是来自Rossum很喜爱的一部70年代英国室内喜剧Monty Python’s Flying Circus。
Rossum的学术背景是阿姆斯特丹大学的数学和计算机科学双料硕士,使用计算机做数学方面的工作在80年代也是一个热门领域,自然而然的,Rossum很熟悉一些老资格的程序设计语言,比如C、Pascal和更古老的、今天已经堪称化石级别的Fortran[1]。这些语言诞生之时,计算机的运算能力还相当孱弱,一台大型机的运算能力甚至比不上今天的一部手机。因此,这些程序语言作为人类使用的自然语言和机器之间的桥梁,不得不更多地照顾机器而非人类。
举一个很简单的例子——内存管理。我们现在使用的开发环境和程序语言,大多数情况下并不用直接指定数据在内存中的存储位置和存储方式,因为内存自动管理早就成为标配,不论是编译器还是操作系统,都有相当强的内存管理能力。但是在很久以前,这些都是痴心妄想——管理内存的本身就是一段程序,一台计算机的硬件资源本身就已经捉襟见肘,还要分一部分资源给这些花里胡哨的偷懒功能那是想都不要想。所以,这些很古老的“高级语言”其实还是保留了不少低级语言的特性,这也逼迫着程序员作为人类必须要更深入地按照计算机的思维来思考问题。
但是这种思考方式让Rossum很不爽——我就想知道a+b等于几,还得花费大量的时间和精力考虑建立两个变量、每个变量是什么类型、分配多少内存地址,这种事情属实不爽。
Rossum比较熟悉和程序语言类似的另一个东西,叫Shell。Shell和一般人比较熟悉的DOS界面有些类似——当然,完全不是一个东西。Shell指的是类Unix操作系统的“外壳”,也就是一个文本交互界面。用户可以在Shell里面输入一些命令,就可以实现操作。比如输入很简单的一行字find /etc -size +1M
就可以搜索所有/etc
目录下体积大于1MB的文件。这些功能要是用C来实现的话,代码妥妥的不止一行。Shell的简洁,其根源在于它实际上调用的是已经存在于操作系统当中的已有程序。简简单单的一句find
四个字母背后是一个名为find的程序,封装了大量的文件系统操作代码。
我们日常使用文本界面(别闹,现在谁还用文本界面……)时,一般是输入一行命令敲个回车执行这个命令,但是也有一种方式,就是用文本编辑器将多个命令写成一个.sh
脚本,运行一下就可以跑里面的所有命令,在大家更熟悉的Windows操作系统当中,可以类比为批处理文件(.bat
)。Shell这种可以通过调用其他模块来实现丰富功能的特性也很大程度上影响到了Python的设计思路。
当时荷兰的数学和计算机研究所在开发一个新的程序语言,叫ABC,Rossum也参与了ABC的开发工作。ABC有一个很有意思的特性——它很接近自然语言。比如,多数程序语言定义一个新的函数的时候,使用的一般是function
或者define
这样的语句,而ABC的写法非常接近人们用英语唠嗑时用的话——HOW TO
。这使得ABC相较于C,代码阅读变得更加友好。但是ABC并不能让Rossum满意。主要原因有四:
- 可扩展性差。
ABC并非模块化语言,这导致ABC的可扩展性非常糟糕。要增加新的功能,请重写。 - 无法操作文件系统。
所以一个无法操作文件的程序语言究竟有什么用? - 编译困难。
ABC的编译器太过于庞大,在当时的技术条件下只能保存在磁带里——80年代的数据磁带和我们相对比较熟悉的音频磁带其实已经一模一样了,要读取磁带的时候,得将磁带放进磁带机,然后类似用放音乐一样,将整卷磁带跑完才能获取完整的数据,效率极其低下。 - 步子太大扯着蛋。
虽然我们0基础的人觉得HOW TO
定义函数挺友好,但是对于已经熟悉了define
定义函数的程序员来说,反而很不习惯了。
这一切都启发Rossum在1989年的圣诞假期期间,自己动手设计了一款程序语言,它具备了ABC的易读易学的特性、具备了Shell模块化调用的思路、同时又具备C这样传统程序语言必备的功能和使用习惯。这个杂烩饭就是Python。
Python的第一个版本就已经奠定了今天诸多Python的基础特性:类、函数、异常处理、核心数据类型以及模块扩展系统,它的很多语法来自C,又有很多语法来自ABC,取双方精华,弃其糟粕,如Python继承了ABC的不缩进不舒服斯基,虽然多数人在码代码的时候都会缩进以确保代码的可读性,但是这更多的是一种工作习惯而非系统的强制要求,即便是完全没有缩进,C编译器也不会在终端上给你甩脸子,但是Python会;同时Python又使用def
定义函数,用=
赋值,这明显是来自传统程序设计的习惯。
在Python解释器的设计思路上,Rossum博采众长,将很多程序语言和非程序语言的特色都挪到了Python上,这看起来让Python有可能成为一锅杂烩饭,但是,Rossum在定义这个新语言的特点的时候,脑子清醒得很——他的诉求非常清晰:让编码人员将尽可能少的时间花费在码代码,而将尽可能多的时间花费在思考程序的运作方式上——即,在计算机目前能做到的逻辑层次上告诉计算机要做什么,但是绝对不浪费时间在深入挖掘程序的运行原理、程序的效率优化这类问题上。能解决问题就好,至于是否有优化空间,再说呗。强大的、可扩展的库让Python能用一句话搞定其他语言里得重新垒地基的功能,至于它调用的那些库又是用什么方式实现的,有时间再看呗。
秉着“能用就行”原则的Python很快就得到了大家的欢迎。而从大的时代背景上看,Python也赶上了好时候。

1990年,Intel发布了空前强大的486处理器,在足够强大的硬件的支撑下,微软在这一年发布了震动业界的Windows 3.0操作系统。这是Windows攻占全球个人桌面市场的第一步,交互友好性成为评价一款软件是否优秀的重要标准。
程序设计界的主流思潮就不再是绞尽脑汁在极其有限的硬件机能的前提下让软件能跑起来,而是逐步切换到了清晰、明确、易于维护和团队协作设计的面向对象的程序设计思路(尽管这样的设计思路在事实上会损失程序的运行性能)。C++和Java这样的面向对象的程序语言就是在90年代逐步发展起来的。Python也搭上了硬件性能起飞的风口,就此开始快速发展。
今天,Python的框架已经基本确定,并且涵盖了大量的非Python的扩展库,这使得Python成为一个庞杂、不那么规整,但是好用、能快速、轻松地解决多种问题的瑞士军刀式的工具。
所以,Why Python?
Why Python?
Python的优势有很多,大致可以归结如下:
- Python is FREE
Python软件和文档以PSF许可发布,PSF许可基本上是原样照抄的BSD许可,不过由于Python本身有一个基金会,因此多加了几条关于基金会组织方面的条款。
所以,Python是开源、自由的软件。它的源代码可以在Python源代码下载页面获取,如果有能力、有硬件资源的话,大可以自己编译Python解释器。 - Python is FREE-OF-CHARGE
自由软件不一定是免费的(Freeware ≠ Free software)。很典型的是RHEL(Red Hat Enterprise Linux),虽然源代码是开放的,任何人都可以自己研究、修改、再发布,但是RHEL本身却是收费的。
但是多数开源的自由软件还是免费的。Python也在其中。而且由于PSF的开放性,将Python嵌入到商业软件当中也是完全合法的。 - Python is FLEXIBLE
Python高度灵活,而且可以各种魔改。Python提供了Embeddable的版本,可以内嵌到其他的软件当中,大家可以在自己的电脑里搜索一下python.exe
,看看它在哪个意料之外的地方出现了,至少在我的电脑里,我在Blender、LibreOffice、UE4、Alias当中都找到了内嵌的Python解释器,说明这些软件都或多或少使用了Python。
而且Python做到了主流平台全部支持,能够完全覆盖Windows、Linux、MacOS三大桌面操作系统,在Android和iOS上也能找到对应的解释器,甚至一些计算器上都能使用Python写程序。 - Python is FEATURE-RICH
得益于强大的外部包的支持,Python的应用领域极为广泛,从科学计算,到网络爬虫,从人工智能,到数据分析,Python都可以找到对应的包来支持。 - Python is FRIENDLY
据说浙江的小学生就开始学Python了。遥想当年我在高中才开始学BASIC和Pascal/Delphi,只能说时代变得太快了。另外,即便是和“入门级语言”——已经被踢出NCRE二级考试的Visual Basic相比,Python也极为简单。它的语法风格很类似自然语言,这使得它被称为“伪代码[2]风格”的语言。能看懂英语基本上也就能把Python的代码的功能猜的八九不离十。
这使得Python设计可以更多地关注程序本身的设计思路,而不是将大量的精力花费在如何实现上。
但是Python当然也不是完美无缺的。
- Python is SLOW
Python的官方实现是解释器,上一篇文章已经介绍了它的缺点——效率低。
虽然就在上面几行说了电脑性能的突飞猛进让低效率不是那么不能忍受,但是在某些特殊领域,如3D图形领域,优化的优劣直观影响到使用体验。虽然Alias和UE集成了Python,但是那是给用户写脚本用的,Alias和UE的3D图形引擎使用的依然是C++这样高效率的语言。 - Python is SHIT on backward compatibility
从Python 2切换到Python 3的痛苦,经历过的人都懂。最常用的print
从方法变成了一个函数,连Hello World都无法兼容。 - Python is SHIT when packing
Python和Linux一样,有“包依赖”这个老大难的问题,一提这三个字,老Linux用户都会脑仁嗡嗡的,我要执行某个功能A,发现功能A依赖于包A,包A下载下来运行不了,一看文档它又依赖于包B、C、D,包C又依赖于包E、F……而且这些包在更新版本的时候一样有可能会导致版本之间互不兼容(虽然概率不太高)。
于是为了解决包依赖问题,Pyinstaller打包的时候会将所有的包全部打进去。于是为了运行一个大小不到1KB的小脚本,打出了一个好几个MB的包。比这更蠢蛋的实现我只知道一个Electron。 - Python is SOURCE-protection unfriendly
Python多数情况下是直接运行.py
脚本的,这东西就是个纯文本,任何人都能看到它的源代码。虽然开放源代码是一种伟大的精神但是既然Python以PSF(山寨版BSD)许可发布,说明人家在道德上并不乐意谴责闭源行为,也允许Python被用于编写闭源软件——可是这个技术架构就对闭源不友好。
虽然pyinstaller可以打包,但是反编译也很容易。所以一些商业化的闭源Python应用甚至不惜用C或者C++将关键功能模块封装然后用Python调用,这顿折腾……
所以,归根到底Python是一个让人快速解决手头问题的工具,它有其特定的适用范围。用它做数据分析是OK的,但是用它写个渲染器可能不太行。但是对于大多数需要码代码的非程序员来说,代码就是用来解决问题的。所以非职业码农学一学Python其实还是有一定价值的。
下一篇,我们将正式开始上手,从搭建Python环境开始。