从Hello World聊起
毕业之后决定转行成为程序员,写下了第一行print("Hello world.")。这成为我了迈入这一行的第一步,而print也是这些年来使用最多的函数了,可这一行代码背后是什么呢?
初识
在python2中print是这么写的print "Hello world",此时的print于我就是一个指令,一个使用了,就会有输出的指令,就是打开水龙头就会出水一般。然后到了python3,写法变成了print("Hello world")。虽然没有细究过为什么要这么改,也偶然看到了"函数化"的说法,为了规范设计思路。所以为什么换个写法设计思路就规范了?这些于我都是谜团,当然,仅仅使用水龙头并不需要了解这么多。
于是,初识阶段,我知道了输入print,屏幕就会有打印。
了解
随着学习的深入,开始有了函数/方法的概念,意识到print("Hello world.")是函数风格的语法,意味着此处的print是一个函数,与其他函数是同一地位的,具有一脉相承的风格。而python2的print就显得有些特立独行了,行为像是一个函数,但是语法上更类似于关键字。至此,我开始有了关键字、函数的概念。可用关键字又有什么不可以呢?同样是水龙头,谁打开放出来的也不会是可乐,这就引入了软件工程中"设计哲学"的概念。代码设计中,应该具有"一致性",你明明做着函数的事情,却长着关键字的脸,这容易引起误会。当然还有“利于扩展”,“函数式编程更友好”等优势,不过这都是后面才理解的东西了。
如果一个python2的项目迁移到python3又该怎么办,于是我开始认识到兼容性,认识到代码的健壮性,认识到代码之外的,关于编程的东西。
这一阶段中,对代码的了解,不再局限于敲出来的一行行字符,我开始跳出眼前的文件,看到项目,看到工程,开始思考如何设计我的代码,如何让我的代码像诗一样优雅(笑。设计模式、软件工程,这些东西都开始有所涉猎。
深入
从print到屏幕上的像素,中间隔着解释器、操作系统、cpu、内存等等等等,他们又做了些什么呢?这些难道只能是黑盒么?不,计算机不应该有秘密。所以我开始随着print向下,看到了解释器。我看到了print先被翻译成了AST,AST又被译成了字节码,字节码又被pvm执行,一路向下,我看到了对操作系统的系统调用。软件忽然串联起来了,从字符串,到字节码,从人类易读的代码,到解释器易读的代码,我开始自上而下的重新认识编程的世界。
这里的每一个步骤都是一门严谨的学科,我无法细致的了解全部,但我知道当我需要的时候,他们不再是黑盒。我也看到了python创造者的想法和创意。
扩展
后来因为需要,开始学习C,C++等编译型语言,开始看指令集、看汇编,然后在某一天意识到,pvm大概是如何运作的,它调用了C的标准库,通过C的标准库调用了操作系统,那操作系统呢?操作系统调用了设备驱动,设备驱动直接操纵了硬件。
所以我能解释python为什么效率低,也知道了直接跳过pvm调用C的原生代码为什么效率高,软件至此和硬件紧密的衔接了。我还是不能说明白pvm做的优化,不能知道操作系统的调度算法有哪些难题,但这就像是一个复杂的魔法,我可能此生无法复现,但它不会再充满神秘。
最后
写到这里有两点感受想与你分享:
从
print("Hello world.")到二进制,计算机系统淋漓的表达着分层设计的哲学:每一层都向上一层提供抽象接口,隐藏下层的复杂性,从而让Python程序员可以简单地调用print()而不需要了解底层硬件的工作原理。任何学科都是有边界的,比如经济学的边界是心理学、物理学的边界是数学,而软件科学的边界大概就是硬件的,我大概不会继续深入的去看cpu的设计和电路,可我清楚他们就在那里,等我需要时伸手可取。
