56 KiB
01-Python语言概述
Life is short ,You need Python !
-- Brce Eckel
一、计算机语言发展历程
编译型与解释型 常见编译型语言 c c++ java 常见解释型语言 shell php python ruby perl
interpreted -- 解释型
Python 一是种解释型语言,与之相对的是编译型语言,虽然两者的区别由于字节码编译器的存在而会有所模糊。这意味着源文件可以直接运行而不必显式地创建可执行文件再运行。解释型语言通常具有比编译型语言更短的开发/调试周期,但是其程序往往运行得更慢。
二进制 计算机能识别的语言,就叫做机器语言,简称机器码。
二进制表示,可以直接被机器识别,上个世纪50年代之前,工程师直接将二进制机器码和数值编写在打孔卡上,通过读卡机读入计算机存储器,然后执行。
汇编语言
为了便于阅读,就将机器代码以英文字符串来表示,于是出现了汇编语言
高级语言 一开始人们只用汇编语言进行程序开发。所以只需要将汇编语言翻译为机器语言就可以了。这是相当直截了当的过程,因为汇编语言的助记符和机器指令是一一对应的关系。所以只需要完成一个能够自动查表并转换的程序即可。很快,这样的程序就被发明了出来。称之为"汇编器"
将常用的一些程序结构编写成对应的助记符,在需要时就使用这个助记符,于是,又在汇编器中引入了宏指令。 宏的引入,催生了程序结构化表达。
结构化表达的方式,给了一些计算机科学人员一些启发。能不能更进一步,使用完全结构化,脱离某个对应机器平台的形式化语言来描述一个源程序?于是,就有了高级语言及其编译器。
开发人员利用高级语言编写程序,然后利用对应的编译器生成中间代码,最后再将中间代码变成机器码。中间代码可以是等价的汇编代码,也可以是其它类型的代码例如JVM 的字节码。
最终处理中间代码的程序可以是一个对应平台的汇编器,也可以是一个解释器。
将编译的最终产物都视为一系列可以被执行的二进制机器码。
静态语言和动态语言
静态语言
C、C++、C#、Java
变量需要声明类型,变量不能改变类型 比如:int x= 1
需要先编译,在运行
动态语言
(脚本语言)
shell python php
使用变量前不需要声明类型 比如:x =1 不需要编译,用解释器解释后运行
Python Python源码 —> 编译器(解释器) —> 字节码 —> 编译器 —> 机器码
二、Python简史
Python是开源(open source)运动的一个成功案例。
Python起源 Python作者: Guido von Rossum,荷兰人. 05年加入Google.
2013年1月从Google离职并加入Dropbox,现就职于Dropbox.
1982年,Guido从阿姆斯特丹大学(University of Amsterdam)获得了数学和计算机硕士学位。然而,尽管他算得上是一位数学家,但他更加享受计算机带来的乐趣。用他的话说,尽管拥有数学和计算机双料资质,他总趋向于做计算机相关的工作,并热衷于做任何和编程相关的活儿。
在那个时候,他接触并使用过诸如Pascal、C、 Fortran等语言。这些语言的基本设计原则是让机器能更快运行。在80年代,虽然IBM和苹果已经掀起了个人电脑浪潮,但这些个人电脑的配置很低 (在今天看来)。比如早期的Macintosh,只有8MHz的CPU主频和128KB的RAM,一个大的数组就能占满内存。所有的编译器的核心是做优化,以便让程序能够运行。为了增进效率,语言也迫使程序员像计算机一样思考,以便能写出更符合机器口味的程序。在那个时代,程序员恨不得用手榨取计算机每一寸的能力。有人甚至认为C语言的指针是在浪费内存。至于动态类型,内存自动管理,面向对象…… 别想了,那会让你的电脑陷入瘫痪。
然而,这种思考方式让Guido感到苦恼。Guido知道如何用C语言写出一个功能,但整个编写过程需要耗费大量的时间 (即使他已经准确的知道了如何实现)。他的另一个选择是shell。Bourne Shell作为UNIX系统的解释器(interpreter)已经长期存在。UNIX的管理员们常常用shell去写一些简单的脚本,以进行一些系统维护的工作,比如定期备份、文件系统管理等等。shell可以像胶水一样,将UNIX下的许多功能连接在一起。许多C语言下上百行的程序,在shell下只用几行就可以完成。然而,shell的本质是调用命令。它并不是一个真正的语言。比如说,shell没有数值型的数据类型,加法运算都很复杂。总之,shell不能全面的调动计算机的功能。
Guido希望有一种语言,这种语言能够像C语言那样,能够全面调用计算机的功能接口,又可以像shell那样,可以轻松的编程。ABC语言让Guido看到希望。ABC是由荷兰的CWI (Centrum Wiskunde & Informatica, 数学和计算机研究所)开发的。Guido在CWI工作,并参与到ABC语言的开发。ABC语言以教学为目的。与当时的大部分语言不同,ABC语言的目标是“"用户感觉更好”"ABC语言希望让语言变得容易阅读,容易使用,容易记忆,容易学习,并以此来激发人们学习编程的兴趣。
比如下面是一段来自Wikipedia的ABC程序,这个程序用于统计文本中出现的词(word)的总数:
a equal b
HOW TO RETURN words document:
PUT {} IN collection
FOR line IN document:
FOR word IN split line:
IF word not.in collection:
INSERT word IN collection
RETURN collection
HOW TO用于定义一个函数。一个Python程序员应该很容易理解这段程序。ABC语言使用冒号(:)和缩进来表示程序块(C语言使用{}来表示程序块)。行尾没有分号。for和if结构中也没有括号()。如果将HOW TO改为def,将PUT行改为collection = [],将INSERT行改为collection.append(word),这就几乎是一个标准的Python函数。上面的函数读起来就像一段自然的文字。
尽管已经具备了良好的可读性和易用性,ABC语言最终没有流行起来。在当时,ABC语言编译器需要比较高配置的电脑才能运行。而这些电脑的使用者通常精通计算机,他们更多考虑程序的效率,而非它的学习难度。除了硬件上的困难外,ABC语言的设计也存在一些致命的问题:
1. 可拓展性差。ABC语言不是模块化语言。如果想在ABC语言中增加功能,比如对图形化的支持,就必须改动很多地方。
2. 不能直接进行IO。ABC语言不能直接操作文件系统。尽管你可以通过诸如文本流的方式导入数据,但ABC无法直接读写文件。输入输出的困难对于计算机语言来说是致命的。你能想像一个打不开车门的跑车么?
3. 过度革新。ABC用自然语言的方式来表达程序的意义,比如上面程序中的HOW TO (如何)。然而对于程序员来说,他们更习惯用function或者define来定义一个函数。同样,程序员也习惯了用等号(=)来分配变量。这尽管让ABC语言显得特别,但实际上增加了程序员的学习难度 (程序员大都掌握不止一种语言)。
4. 传播困难。ABC编译器很大,必须被保存在磁带(tape)上。当时Guido在访问的时候,就必须有一个大磁带来给别人安装ABC编译器。 这样,ABC语言就很难快速传播。
IBM tape drive:读写磁带
1989年,为了打发圣诞节假期,Guido开始写Python语言的编译/解释器。Python来自Guido所挚爱的电视剧Monty Python's Flying Circus (BBC1960-1970年代播放的室内情景幽默剧,以当时的英国生活为素材)。他希望这个新的叫做Python的语言,能实现他的理念(一种C和shell之间,功能全面,易学易用,可拓展的语言)。Guido作为一个语言设计爱好者,已经有过设计语言的(不很成功)的尝试。这一次,也不过是一次纯粹的hacking行为。
Python的诞生
1991年,第一个Python编译器(同时也是解释器)诞生。它是用C语言实现的,并能够调用C库(.so文件)。从一出生,Python已经具有了:类(class),函数(function),异常处理(exception),包括表(list)和词典(dictionary)在内的核心数据类型,以及模块(module)为基础的拓展系统。
最初的Python logo: 由Guido的兄弟Just von Rossum设计
Python语法很多来自C,但又受到ABC语言的强烈影响。来自ABC语言的一些规定直到今天还富有争议,比如强制缩进。但这些语法规定让Python容易读。另一方面,Python聪明的选择服从一些惯例(特别是C语言的惯例)。比如使用等号赋值,使用def来定义函数。Guido认为,如果"常识"上确立的东西,没有必要过度纠结。
Python从一开始就特别在意可拓展性(extensibility)。Python可以在多个层次上拓展。从高层上,你可以引入.py文件。在底层,你可以引用C语言的库。Python程序员可以快速的使用Python写.py文件作为拓展模块。但当性能是考虑的重要因素时,Python程序员可以深入底层,写C程序,编译为.so文件引入到Python中使用。Python就好像是使用钢构建房一样,先规定好大的框架。而程序员可以在此框架下相当自由的拓展或更改。
最初的Python完全由Guido本人开发。Python得到Guido同事的欢迎。他们迅速的反馈使用意见,并参与到Python的改进。Guido和一些同事构成Python的核心团队。他们将自己大部分的业余时间用于hack Python (也包括工作时间,因为他们将Python用于工作)。随后,Python拓展到CWI之外。Python将许多机器层面上的细节隐藏,交给编译器处理,并凸显出逻辑层面的编程思考。Python程序员可以花更多的时间用于思考程序的逻辑,而不是具体的实现细节 (Guido有一件T恤,写着:人生苦短,我用Python)。这一特征吸引了广大的程序员。Python开始流行。
我们不得不暂停我们的Python时间,转而看一看这时的计算机概况。1990年代初,个人计算机开始进入普通家庭。Intel发布了486处理器,windows发布window 3.0开始的一系列视窗系统。计算机的性能大大提高。程序员开始关注计算机的易用性 (比如图形化界面)。
Windows 3.0
由于计算机性能的提高,软件世界也开始随之改变。硬件足以满足许多个人电脑的需要。硬件厂商甚至渴望高需求软件的出现,以带动硬件的更新换代。C++和Java相继流行。C++和Java提供了面向对象的编程范式,以及丰富的对象库。在牺牲了一定的性能的代价下,C++和Java大大提高了程序的产量。语言的易用性被提到一个新的高度。我们还记得,ABC失败的一个重要原因是硬件的性能限制。从这方面说,Python要比ABC幸运许多。
另一个悄然发生的改变是Internet。1990年代还是个人电脑的时代,windows和Intel挟PC以令天下,盛极一时。尽管Internet为主体的信息革命尚未到来,但许多程序员以及资深计算机用户已经在频繁使用Internet进行交流 (包括email和newsgroup)。Internet让信息交流成本大大下降。一种新的软件开发模式开始流行:开源 (open source)。程序员利用业余时间进行软件开发,并开放源代码。1991年,Linus在comp.os.minix新闻组上发布了Linux内核源代码,吸引大批hacker的加入。Linux和GNU相互合作,最终构成了一个充满活力的开源平台。
硬件性能不是瓶颈,Python又容易使用,所以许多人开始转向Python。Guido维护了一个maillist,Python用户就通过邮件进行交流。Python用户来自许多领域,有不同的背景,对Python也有不同的需求。Python相当的开放,又容易拓展,所以当用户不满足于现有功能,很容易对Python进行拓展或改造。随后,这些用户将改动发给Guido,并由Guido决定是否将新的特征加入到Python或者标准库中。如果代码能被纳入Python自身或者标准库,这将极大的荣誉。Python自身也因此变得更好。(Guido不得不作出许多决定,这也是他被称为Benevolent Dictator For Life的原因)
Python被称为"Battery Included",是说它以及其标准库的功能强大。这些是整个社区的贡献。Python的开发者来自不同领域,他们将不同领域的优点带给Python。比如Python标准库中的正则表达(regular expression)是参考Perl,而lambda, map, filter, reduce函数参考Lisp。Python本身的一些功能以及大部分的标准库来自于社区。Python的社区不断扩大,进而拥有了自己的newsgroup,网站(python.org),以及基金 (Python Software Foundation)。从Python 2.0开始,Python也从maillist的开发方式,转为完全开源的开发方式。社区气氛已经形成,工作被整个社区分担,Python也获得了更加高速的发展。 (由于Guido享有绝对的仲裁权,所以在Python早期maillist的开发时代,不少爱好者相当担心Guido的生命。他们甚至作出假设:如果Guido挂了的话,Python会怎样。见If Guido was hit by a bus)
到今天,Python的框架已经确立。Python语言以对象为核心组织代码(Everything is object),支持多种编程范式(multi-paradigm),采用动态类型(dynamic typing),自动进行内存回收(garbage collection)。Python支持解释运行(interpret),并能调用C库进行拓展。Python有强大的标准库 (battery included)。由于标准库的体系已经稳定,所以Python的生态系统开始拓展到第三方包。这些包,如Django, web.py, wxpython, numpy, matplotlib,PIL,将Python升级成了物种丰富的热带雨林。
今天Python已经进入到3.0的时代。由于Python 3.0向后不兼容,所以从2.0到3.0的过渡并不容易。另一方面,Python的性能依然值得改进,Python的运算性能低于C++和Java(见Google的讨论)。Python依然是一个在发展中的语言。我期待看到Python的未来。
Python启示录 Python崇尚优美、清晰、简单,是一个优秀并广泛使用的语言 (TIOBE语言排行第八,Google的第三大开发语言,Dropbox的基础语言,豆瓣的服务器语言)。这个世界并不缺乏优秀的语言,但Python的发展史作为一个代表,带给我许多启示。
在Python的开发过程中,社区起到了重要的作用。Guido自认为自己不是全能型的程序员,所以他只负责制订框架。如果问题太复杂,他会选择绕过去,也就是cut the corner。这些问题最终由社区中的其他人解决。社区中的人才是异常丰富的,就连创建网站,筹集基金这样与开发稍远的事情,也有人乐意于处理。如今的项目开发越来越复杂,越来越庞大,合作以及开放的心态成为项目最终成功的关键。
Python从其他语言中学到了很多,无论是已经进入历史的ABC,还是依然在使用的C和Perl,以及许多没有列出的其他语言。可以说,Python的成功代表了它所有借鉴的语言的成功。同样,Ruby借鉴了Python,它的成功也代表了Python某些方面的成功。每个语言都是混合体,都有它优秀的地方,但也有各种各样的缺陷。同时,一个语言"好与不好"的评判,往往受制于平台、硬件、时代等等外部原因。程序员经历过许多语言之争。我想,为什么不以开放的心态和客观的分析,去区分一下每个语言的具体优点缺点,去区分内部和外部的因素。说不定哪一天发现,我不喜欢的某个语言中,正包含了我所需要的东西。
无论Python未来的命运如何,Python的历史已经是本很有趣的小说。
三、Python特性
-
面向对象的特性 面向对象的程序设计抽象出对象的行为和属性,把行为和属性分离开,但是又合理的组织在一起。它消除了 保护类型、抽象类、接口等面向对象的元素,使得面向对象的概念更容易理解。
-
简单性 没有分号,使用缩进的方式分隔代码,代码简洁,短小,易于阅读。
-
内置的数据结构 类似于Java中集合类的功能。python的数据结构包括元组,列表,字典等。元组相当于“"读”"数组,列表 可以作为可变长度的数组使用,字典相当于java中的hashtable类型。
-
健壮性 提供异常退出机制,能捕获程序的异常情况。
-
跨平台性 python会先先编译成与平台相关的二进制码,然后再解释执行,这种方式和java类似。
-
可拓展性 python是用c开发的语言,因此可以使用c扩展python,可以给python添加新的模块、新的类。同时 python可以嵌入到c,c++语言开发的项目中,使语言具备脚本语言的特性。
-
动态性 python不需要另外声明变量,直接赋值即可以创建一个新的变量
-
强类型语言 python会根据赋值表达式的内容决定变量的数据类型。python在内部建立了管理这些变量的机制,出现在 同一个表达式的不同类型的变量需要做类型转换。
-
应用广泛 python有许多第三方的库支持。例如:PIL库应用于图像处理,numpy库应用于数学计算,wxpython库应 用于GUI程序的设计,Django库应用于web程序的开发等。
c c++ java python golang
各种流行语言hello world对比:
#!/usr/bin/env bash
echo "hello world"
# cat HelloWorld.c
#include<stdio.h>
int main(int agrc,char *agrv[]){
int language = 1;
printf("Hello World!I am C! language: %d\n", language);
return 0;
}
# cat HelloWorld.c++
#include<iostream>
using namespace std;
int main(){
int language = 2;
cout << "Hello World! I am C++! Language: " << language <<endl;
return 0;
}
# cat HelloWorld.java
public class HelloWorld{
public static void main (String[] args){
int language = 3;
System.out.format("Hello World! I am java!Language:%d\n",language)
}
}
# cat HelloWorld.py
#!/usr/bin/env python
language = 4
print("Hello World! I am python3! Language:{}".format(language))
四、Python之禅
那谁说,要想学好一门编程语言,你就需要接受这门语言的哲学。那么如果你想精通Python,就需要践行 Python背后的设计哲学。
Python之父是荷兰人Guido van Rossum,被誉为历史上最伟大的12名程序员之一。他在设计Python 时,目的是设计出一种优美而强大,提供给非专业程序设计师使用的语言,同时采取开放策略,使Python能 够完美结合如C 、C++和Java等其他语言。
而对Python哲学的最好阐述,莫过于核心开发者Tim Peters所总结的"python之禅"(The Zen of Python)了。
启动Python解释器后,输入 import this 就可以看到全文了
>>> import this
The Zen of Python
Python 之禅
Beautiful is better than ugly.
美胜于丑
Explicit is better than implicit.
显胜于隐
Simple is better than complex.
简胜于繁
Complex is better than complicated.
繁胜于杂
Flat is better than nested.
平胜于迭
Sparse is better than dense.
疏胜于密
Readability counts.
读胜于写
Special cases aren't special enough to break the rules.
规则胜于特例
Although practicality beats purity.
实用胜于单纯
Errors should never pass silently.
告错胜于沉默
Unless explicitly silenced.
沉默胜于吵闹
In the face of ambiguity, refuse the temptation to guess.
拒绝胜于猜测
There should be one-- and preferably only one --obvious way to do it.
唯一胜于显然
Although that way may not be obvious at first unless you're Dutch.
显然不是荷兰
Now is better than never.
现在胜于永不
Although never is often better than *right* now.
永不胜于匆猝
If the implementation is hard to explain, it's a bad idea.
凡值得说,必易于说
If the implementation is easy to explain, it may be a good idea.
反之则不然
Namespaces are one honking great idea -- let's do more of those!
名可名, 请常名
• 优美胜于丑陋(Python 以编写优美的代码为目标)
• 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)
• 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)
• 复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
• 扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)
• 间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)
• 可读性很重要(优美的代码是可读的)
• 即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)
• 不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)
• 当存在多种可能,不要尝试去猜测
• 而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)
• 虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )
• 做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)
• 如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)
• 命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)
对于翻译,我没有什么发言权。我对翻译的了解大多来自思果先生的《翻译研究》和《翻译新究》这两本书。思果先生是著名的散文家、翻译家。说来惭愧,我还未能有幸拜读他的散文,不过只是这两本翻译论著就已经感受到老人家文字功底之深了。每次读都会觉得很舒服,仿佛先生坐在面前谆谆教导翻译的经验,时常如醍醐灌顶,发出“哦,原来还能这样翻译啊”的感叹。我最喜欢的是他老人家说的我们翻译要翻译得像中文这种思想,我想翻译毕竟是给中国人看的嘛,尽量不要让读者读译文读的太辛苦,所以有关翻译,推荐译者去读读《翻译研究》和《翻译新究》这两本书。
另一方面,学 Python 必须知道的一点,我觉得应该是 import this,这是什么?这就是 Python 之禅。编程语言其实就是把人类的思想翻译给机器听,Python 之禅就是这种翻译工作的理念。都说 Python 是一门优雅简洁、易学易懂的编程语言,我觉得科技界的译者同仁也可以参考,下面是我对 Python 之禅的译文。
Python 之禅
Tim Peters 著
美比丑好,明比涩强。
简胜于繁,繁强于难。
平言莫绕,宜疏莫密。
行文如水,易懂为王。
勿提特例,皆循此规。
实虽胜纯,识错必究。
若需留证,亦要言明。
不明其理,追根问底。
必有一法,可解谜题。
汝非龟叔,求之故难。
立足当下,行必有方。
行难言喻,所思欠妥。
行易言表,所思可嘉。
名正易识,善莫大焉!
下面,容我一句一句把我的启示说来给大家听听。
Beautiful is better than ugly.
美比丑好。
编程之美已经衍生出来了众多之美标题党。而翻译之美,百余年前严复先生提出的信达雅更是世人皆知,就算我们这些后辈没有前人那么深厚的国文功底,也别翻译得让人读得皱眉头。
Explicit is better than implicit.
明比涩强。
编程主张显性,不提倡隐性。翻译也要清清楚楚、明明白白,别拐弯抹角,让人去猜。
Simple is better than complex.
简胜于繁。
写代码要精简,翻译也不能繁琐,译文中有一些常见问题,呆鸟总结下来就是:“一个一个满天飞,你我他们说不腻。所有如果的时候,被来被去被不完。” 这是英文的习惯,我们中国人说话没这么啰里啰嗦,没必要那么老实地按原文译出。
Complex is better than complicated.
繁强于难。
当码农已经很难了,代码写得尽量让同事和未来的自己读起来轻松一点,算得上功德。翻译更是,因为读者更多,不能让不懂英文的人读起来觉得译文比英文还难理解,最后被逼得自学英语去读英文原著。我算是其中一个。
Flat is better than nested.
平言莫绕。
编程讲究扁平,不鼓励嵌套,翻译也可以这么干,最好像梯田一样平铺直叙,别搞得如九连环一般,要烦劳读者去解。
Sparse is better than dense.
宜疏莫密。
编程说的是不要想着用一行代码实现过多的功能,多些写几行没关系,看的清楚,易于理解。我们中文也不喜欢大长句子,一段话几十上百字一逗到底,甚至都不带打嗑呗儿,那可不行,读起来心累。
Readability counts.
行文如水,易懂为王。
编程也好翻译也罢,越容易让人读明白越好!
Special cases aren't special enough to break the rules.
勿提特例,皆循此规。
没有规矩,不成方圆,写代码讲究语言规则,多一个字母,少一个空格,都会报错。翻译这点就宽容多了,没有编译一说,但也不能因此就老拿原文就是怎样怎样说事儿,中文有中文的行文规矩,虽然不需要编译,也做不到译者前辈改译文如重译的境界,但也要多读几遍译文,自己编译一下。
Although practicality beats purity.
Errors should never pass silently.
实虽胜纯,识错必究。
这里说的是实用性比语言的纯粹更重要,但发现错误也一定要说明清楚,计算机是可以 Debug 的,翻译没有,不过我们有万千读者,我希望读者能多与译者沟通,指正勘误,帮助译者优化译文,在此,呆鸟先拜谢了。
Unless explicitly silenced.
若需留证,亦要言明。
编程有注释,翻译有译注。有些英文典故也好,俗语也罢,实在用中文解释不通的,可以用译注说明,起码也算证明这是经过译者思考了的。
In the face of ambiguity, refuse the temptation to guess.
不明其理,追根问底。
这里只说翻译,一定要多读原文,读不懂或理解不清的要多读几遍,多查字典,按思果先生的说法,一本字典是不够的,要想译好文章,多查字典才行。好在我们现在有互联网了,查单词、查典故、查人物、查事件都比当年方便百倍,所以不懂莫猜,请多查多验。
There should be one — and preferably only one — obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
必有一法,可解谜题。汝非龟叔,求之故难。
Dutch 指的是龟叔,Python 的生身父母,荷兰人,大神!所以这两句可以这么认为,原文只有一个,译文也应该只有一个,好的译文就像一字千金的《吕氏春秋》一样,改一字都会破坏整体的美感,你做不到,那是因为你不是翻译大神!好吧,我承认,我现在还理解不了这种境界,貌似除了吕不韦,也还没听谁再这么说过,再说 Python 也一直在优化,所以我还是接着改译文吧。
Now is better than never.
Although never is often better than right now.
立足当下,行必有方。
这句话的意思呆鸟觉得应该是,现在开始做,比永远都不做强。但永远都不做,比想起来就干,不准备、不思考、没方向的蛮干、胡干要强。也就是说,翻译的不好,还不如别翻译,貌似很多事都是如此。
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
行难言喻,所思欠妥。行易言表,所思可嘉。
这句话好理解,译文说的明白,好懂易读就能算好译文了,晦涩难懂,就是糟糕的译文。
Namespaces are one honking great idea — let's do more of those!
名正易识,善莫大焉!
命名空间是编程的事情,在翻译里可以当它说的是名词,已经被大家接受的名词不难,难的是一些少见多怪的名词,比如 Informational Interview,绞尽脑汁翻译成信息化约谈,网上也有翻译成信息化面试的,实际上人家说的是面试前找公司里的招聘经理或部门员工,约出来喝喝咖啡聊聊天,认识一下,了解下公司,老外喜欢这么干,国内这样干的应该都是比较高层了,我等底层人士估计约不出来。所以这个词很少见,很难翻译,求指教。还有诸如 take-home assignment、democratize access、raw intelligence、hustle and grit 这样的,真是叫人不知道该怎么下手好,所以说,把名词翻译好了,真是善莫大焉了。
python之禅乃是python中的彩蛋之一,其实还有其他彩蛋
彩蛋2:反地心引力漫画
>>> import antigravity
导入 antigravity,浏览器会跳转到一副漫画网页 http://xkcd.com/353/,漫画非常有意思。
彩蛋3:Hello world!
>>> import __hello__
Hello world!
彩蛋4:No chance!
想当年我写得了一手流利的 C 代码,大括号用的出神入化,无处不括号成了我写代码的风格…
想当年我还和别人为“大括号是放在一行结尾还是另起一行”争论不休,撸起袖子,指点江山激扬文字…
而我接触了 Python 以后,这门神奇的语言,竟然省去了大括号,我无比想念它,为此我还吟诗一首…啊,大括号~我,想念你!
后来我发现了 braces 库可以使用大括号的功能,我激动的像个帕金森症的晚期患者,哆里哆嗦的导入库,然后…
五、Python 家族
CPython CPython是标准Python,也是其他Python编译器的参考实现。通常提到"Python"一词,都是指CPython。 CPython由C编写,将Python源码编译成CPython字节码,由虚拟机解释执行。没有用到JIT等技术,垃圾回收方面 采用的是引用计数。 所以当有人问道Python是解释执行还是编译执行,可以这样回答:Python(CPython)将Python源码编译成 CPython字节码,再由虚拟机解释执行这些字节码。 如果需要广泛用到C编写的第三方扩展,或让大多数用户都能直接使用你的Python代码,那么还是使用CPython 吧。
Jython Jython在JVM上实现的Python,由Java编写。Jython将Python源码编译成JVM字节码,由JVM执行对应的字节码。因此能很好的与JVM集成,比如利用JVM的垃圾回收和JIT,直接导入并调用JVM上其他语言编写的库和函数。 对于想在JVM上使用Python简化工作流程,或者出于某些原因需要在Python语言中使用Java的相关代码,同时无 需用到太多CPython扩展的用户来说,极力推荐Jython。 IronPythonIronPython与Jython类似,所不同的是IronPython在CLR上实现了Python,即面向.NET平台,由C#编写。IronPython将源码编译成TODO CLR,同样能很好的与.NET平台集成。即与Jython相同,可以利用.NET框架的 JIT、垃圾回收等功能,能导入并调用.NET上其他语言编写的库和函数。IronPython默认使用Unicode字符串。 另外,Python Tools for Visual Studio可以将CPython和IronPython无缝集成进VS中。如果仅需要在Windows上开发较大的Python项目。条件允许的情况下,IronPython是个不错的选择。
PyPy 这里说的PyPy是指使用RPython实现,利用Tracing JIT技术实现的Python,而不是RPython工具链。PyPy可以选 择多种垃圾回收方式,如标记清除、标记压缩、分代等。 相对于CPython,PyPy的性能提升非常明显,但对第三方模块的支持真心是弱爆了。比如无法很好的支持使用 CPython的C API编写的扩展,完全不支持使用SWIG、SIP等工具编写的扩展。就连NumPy,也要在编译器的层面 上从头实现。即使实现了,也只能在Python层面中使用,无法供其他第三方模块在非Python环境中使用。关于 PyPy,后续会尝试用一篇完整的文章来介绍。不过我的这一篇文章中对PyPy和下面的Pyston有更详细的描述。
Pyston
Pyston由Dropbox开发,使用C++11编写,采用Method-at-a-time-JIT和Mark Sweep——Stop the World的GC技术。Pyston使用类似JavaScript V8那样的多层编译,其中也用到了LLVM来优化代码。Pyston正在发展中,还不成 熟。但其前景是非常值得看好的,如果没像Google的Unladen Swallow那样死掉的话。
六、Python应用场景
- 网站运维是Python(继Bash,Perl之后)的一大领域。
- 抓取第三方数据是Python爬虫的领域。
- 金融数据分析。
- 网站中许多核心都是C/C++/Java开发的,如Redis,Memcached,ngnix,消息队列,Hadoop等。但是客户端中Python必须列入其中。
- Python有许多实现(利用其他语言来写Python解释器),不仅仅是CPython。它可以基于Java,C,Python自己,C#,Ruby,Javascript等各个语言制作。可以这么说,Python的底层实现语言是最丰富的,绝对没有之一。所以它可以和C/C++/Java/C#/Ruby/Javascript等各类语言直接交换数据。不仅仅通过REST/JSON/XML交换。Java/C/C#/Ruby/Javascript使用的场景它都可以插足
Windows编程 Python不仅可以在Unix类型的操作系统上应用,同样可以在Windows系统里有很好的表现。通过添加PythonWin模块,就可以通过COM 形式调用和建立各种资源,包括调用注册表、ActiveX控件以及各种COM等工作,最常见的例子就是通过程序对Office文档进行处理,自动生成文档 和图表。 通过Python,还可以利用py2exe模块生成exe应用程序。还有许多其他的日常维护和管理工作也可以交给Python来做,从而减少维护的工作 量。利用Python,你还可以开发出象VB,VC,Delphi那样的GUI程序,但却可以在多个平台上执行。这在许多方面并不逊色于Java。
多媒体 利用PIL、Piddle、ReportLab等模块,你可以处理图象、声音、视频、动画等,从而为你的程序添加亮丽的光彩。动态图表的生成、统计分析图 表都可以通过Python来完成。另外,还有OpenGL。利用PyOpenGl模块,你可以非常迅速的编写出三维场景。
科学计算 Python可以广泛的在科学计算领域发挥独特的角色。有许多模块可以帮助你在计算巨型数组、矢量分析、神经网络等方面高效率完成工作。尤其是在教育科研方面,可以发挥出独特的优势。
网络编程 Python可以非常方便的完成网络编程的工作,提供了众多的解决方案和模块,可以非常方便的定制出自己的服务器软件,无论是c/s,还是b/s模式,都有很好的解决方法。
图形用户界面 Python可以非常方便的实现GUI编程,通过Tkinter,wxPython,QT等等模块,你就可以根据需要编写出强大的跨平台的用户界面程序。
开发环境与编辑器 Python程序的开发工具较多,既有IDLE,PythonWin这样的免费工具, 也有一些商业工具 集成开发环境(IDE): IDLE:这是Python里边自带的,基本上可以满足一般开发需要,请参考cnIDLE。 PythonWin:这是基于Windows平台的编辑开发环境,基本上可以满足一般开发需要。 PythonWorks Pro Wing IDE Komodo 代码编辑器: LEO:完全由Python编写的程序代码编写辅助工具,可运行在多种操作系统中,支持独特的程序代码管理方式。 gVim:相当专业的代码编辑器,可运行在多种操作系统中,支持Python扩展。 Emacs:Unix系统中常用的工具。 SciTE:简单易用的代码编辑器,支持unicode编辑。
嵌入和扩展 Python可以嵌入到其它应用程序中,也可以通过C/C++编写扩展模块,从而可以提高程序的运行速度或者完成只有通过C/C++才能完成的工作。现在 Python已经可以和C#相结合,并且结合到Visual Studio里边,实现微软的.Net思想。如果你会C语言,再学习Python,这将是一个非常棒的一种选择。 如果你掌握了Python,想在Java里应用它,你可以采用Jython。Jython是采用Java语言实现的Python。这样,你只 要按照Python的语法,就可以调用Java的各种类库,快速的编写出基于Java的程序。也就是通过Jython,编写Java程序。这样就可以更为 快速的实现Java的功能。Python在面向对象方面和Java是相通的。 除了c/c++和java, Python 目前还可以和Delphi、VB结合。
游戏编程 Python在很早的时候就是一种游戏编程的辅助工具。在《星球大战》中扮演了重要的角色。在"贝斯(Abyss)"、"星球之旅(Star Trek)"、"Indiana Jones"超级大片中担当特技和动画制作的工业光魔公司(Industrial Light)就采用Python制作商业动画。目前,通过Python完全可以编写出非常棒的游戏程序。
企业与政务应用 目前,Python已经成功的实现企业级应用,在全球,已经有很多公司采用Python进行企业级软件的开发和应用,比如:ERP和CRM这样的应用。同时,通过Python技术,成功的实现了许多政务应用。
比较有名的网站或应用
其中有一些是用python进行开发,有一些在部分业务或功能上使用到了python,还有的是支持python作为扩展脚本语言。数据大部分来自Wikepedia和Quora。
Reddit - 社交分享网站,最早用Lisp开发,在2005年转为python
Dropbox - 文件分享服务
豆瓣网 - 图书、唱片、电影等文化产品的资料数据库网站
Django - 鼓励快速开发的Web应用框架
Fabric - 用于管理成百上千台Linux主机的程序库
EVE - 网络游戏EVE大量使用Python进行开发
Blender - 以C与Python开发的开源3D绘图软件
BitTorrent - bt下载软件客户端
Ubuntu Software Center - Ubuntu 9.10版本后自带的图形化包管理器
YUM - 用于RPM兼容的Linux系统上的包管理器
Civilization IV - 游戏《文明4》
Battlefield 2 - 游戏《战地2》
Google - 谷歌在很多项目中用python作为网络应用的后端,如Google Groups、Gmail、
Google Maps等,Google App Engine支持python作为开发语言
NASA - 美国宇航局,从1994年起把python作为主要开发语言
Industrial Light & Magic - 工业光魔,乔治·卢卡斯创立的电影特效公司
Yahoo! Groups - 雅虎推出的群组交流平台
YouTube - 视频分享网站,在某些功能上使用到python
Cinema 4D - 一套整合3D模型、动画与绘图的高级三维绘图软件,以其高速的运算和强大
的渲染插件著称
Autodesk Maya - 3D建模软件,支持python作为脚本语言
gedit - Linux平台的文本编辑器
GIMP - Linux平台的图像处理软件
Minecraft: Pi Edition - 游戏《Minecraft》的树莓派版本
MySQL Workbench - 可视化数据库管理工具
Digg - 社交新闻分享网站
Mozilla - 为支持和领导开源的Mozilla项目而设立的一个非营利组织
Quora - 社交问答网站
Path - 私密社交应用
Pinterest - 图片社交分享网站
SlideShare - 幻灯片存储、展示、分享的网站
Yelp - 美国商户点评网站
Slide - 社交游戏/应用开发公司,被谷歌收购
七、Python编程风格
这篇文档改编自Guido最初的《Python风格指南》一文,并从《Barry's style guide》中添加了部分内容。在有冲突的地方,应以Guido风格为准。这篇PEP仍然尚未完成(实际上,它可能永远都不会完成)。
在这篇风格指导中的一致性是重要的。在一个项目内的一致性更重要。在一个模块或函数内的一致性最重要。但最重要的是:知道何时会不一致——有时只是没有实施风格指导。当出现疑惑时,运用你的最佳判断,看看别的例子,然后决定怎样看起来更好。并且要不耻下问!
a = 8
a=8
{"a" : 8, "b":9}
打破一条既定规则的两个好理由: 1、当应用这个规则是将导致代码可读性下降,即便对某人来说,他已经习惯于按这条规则来阅读代码了。 2、为了和周围的代码保持一致而打破规则(也许是历史原因),虽然这也是个清除其它混乱的好机会。
代码的布局 1、缩进
4个空格一个缩进层次。对于确实古老的代码,你不希望产生混乱,可以继续使用8空格的制表符(8-space tabs)。
2、制表符还是空格 永远不要混用制表符和空格。最流行的Python缩进方式是仅使用空格,其次是仅使用制表符,混合着制表符和空格缩进的代码将被转换成仅使用空格。
对于新的项目,强烈推荐仅使用空格而不是制表符。
3、行的最大长度 周围仍然有许多设备被限制在每行80字符:而且,窗口限制在80个字符。使将多个窗口并排放置成为可能。在这些设备上使用默认的折叠方式看起来有点丑陋。因此,请将所有行限制在最大79字符,对顺序排放的大块文本(文档字符串或注释),推荐将长度限制在72字符。
折叠长行的首选方法是使用Pyhon支持的圆括号,方括号和花括号内的行延续。如果需要,可以在表达式周围增加一对额外的圆括号,但是有时使用反斜杠看起来更好,确认恰当得缩进了延续的行。
4、空行 用两行空行分割顶层函数和类的定义,类内方法的定义用单个空行分割,额外的空行可被用于(保守的)分割相关函数组成的群,在一组相关的单句中间可以省略空行。
当空行用于分割方法的定义时,在‘class’行和第一个方法定义之间也要有一个空行。在函数中使用空行时,请谨慎的用于表示一个逻辑段落。
5、导入 通常应该在单独的行中导入(Imports),例如: No: import sys, os Yes:import sys import os
但是这样也是可以的:
from types import StringType, ListType
Imports 通常被放置在文件的顶部,仅在模块注释和文档字符串之后,在模块的全局变量和常量之前。
Imports应该有顺序地成组安放:
1、标准库的导入(Imports )
2、相关的主包(major package)的导入(即,所有的email包在随后导入)
3、特定应用的导入(imports)
你应该在每组导入之间放置一个空行,对于内部包的导入是不推荐使用相对导入的,对所有导入都要使用包的绝对路径。
6、表达式和语句中的空格 Guido不喜欢在以下地方出现空格: 紧挨着圆括号,方括号和花括号的,
如:"spam( ham[ 1 ],{ eggs:2 } )",要始终将它写成"spam(ham[1],{eggs:2})"。
紧贴在逗号,分号或冒号前的,
要始终将它写成 "if x == 4:print x,y:x,y = y,x"。
紧贴着函数调用的参数列表前开式括号(open parenthesis )的,
如:"spam (1)"。要始终将它写成"spam(1)"。
紧贴在索引或切片,开始的开式括号前的,
如: "dict ['key'] = list [index]"。要始终将它写成"dict['key'] = list[index]"。
在赋值(或其它)运算符周围的用于和其它并排的一个以上的空格,如:
x= 1
y= 2
long_variable = 3
要始终将它写成
x = 1
y = 2
long_variable = 3
其它建议 始终在这些二元运算符两边放置一个空格:赋值(=), 比较(==,<,>,!=,<>,<=, >=,in,not in,is,is not),布尔运算 (and,or,not)。
不要在用于指定关键字参数或默认参数值的'='号周围使用空格,例如:
def complex(real, imag=0):
return magic(r=real, i=imag)
不要将多条语句写在同一行上:
No: if foo == 'blah':do_blah_thing()
Yes:if foo == 'blah':
do_blah_thing()
No:do_one():do_two():do_three()
Yes:do_one()
do_two()
do_three()
7、注释 同代码不一致的注释比没注释更差。当代码修改时,始终优先更新注释!注释应该是完整的句子,如果注释是一个短语或句子,首字母应该大写,除非他是一个以小写字母开头的标识符(永远不要修改标识符的大小写)。
如果注释很短,最好省略末尾的句号。注释块通常由一个或多个由完整句子构成的段落组成,每个句子应该以句号结尾。你应该在句末,句号后使用两个空格
用英语书写时,断词和空格是可用的。非英语国家的Python程序员:请用英语书写你的注释,除非你120%的确信这些代码不会被不懂你的语言的人阅读。
8、注释块 注释块通常应用于跟随着一些(或者全部)代码并和这些代码有着相同的缩进层次。注释块中每行以‘#’和一个空格开始(除非他是注释内的缩进文本)。注释块内的段落以仅含单个‘#’的行分割。注释块上下方最好有一空行包围(或上方两行下方一行,对一个新函数定义段的注释)。
9、行内注释 一个行内注释是和语句在同一行的注释,行内注释应该谨慎使用,行内注释应该至少用两个空格和语句分开,它们应该以'#'和单个空格开始。
如果语意是很明了的,那么行内注释是不必要的,事实上是应该被移除的。不要这样写:
x = x+1 # Increment x x = x+1 # Compensate for border
10、文档字符串 应该一直遵守编写好的文档字符串的约定PEP 257 [3]。为所有公共模块,函数,类和方法编写文档字符串。文档字符串对非公开的方法不是必要的,但你应该有一个描述这个方法做什么的注释。这个注释应该在"def"这行后。
PEP 257 描述了好的文档字符串的约定。一定注意,多行文档字符串结尾的"""应该单独成行,例如:
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first。
"""
对单行的文档字符串,结尾的"""在同一行也可以。
对单行的文档字符串,结尾的"""在同一行也可以。
11、命名约定 Python库的命名约定有点混乱,所以我们将永远不能使之变得完全一致,不过还是有公认的命名规范的。新的模块和包(包括第三方的框架)必须符合这些标准,但对已有的库存在不同风格的,保持内部的一致性是首选的。
描述:命名风格 有许多不同的命名风格。以下的有助于辨认正在使用的命名风格,独立于它们的作用。以下的命名风格是众所周知的:
b (单个小写字母)
B (单个大写字母)
Lowercase(小写)
lower_case_with_underscores(有下划线的小写)
UPPERCASE(大写)
UPPER_CASE_WITH_UNDERSCORES(有下划线的大写)
CapitalizedWords (或 CapWords,CamelCase这样命名是因为可从字母的大小写分出单词。这有时也被当作StudlyCaps。
mixedCase (与CapitalizedWords的不同在于首字母小写!)
Capitalized_Words_With_Underscores(有下划线的首字母大写) (丑陋!)
另外,以下用下划线作前导或结尾的特殊形式是被公认的(这些通常可以和任何习惯组合):
_single_leading_underscore
(单个下划线作前导):弱的"内部使用(internal use)"标志。 (例如,"from M import *"不会导入以下划线开头的对象)。
single_trailing_underscore_
(单个下划线结尾): 用于避免与Python关键词的冲突,例如:"Tkinter.Toplevel(master,class_='ClassName')"。
__double_leading_underscore
(双下划线):从Python 1.4起为类私有名。
说明:命名约定
应避免的名字。永远不要用字符‘l’(小写字母el(就是读音,下同)),‘O’(大写字母oh),或‘I’(大写字母eye)作为单字符的变量名。在某些字体中这些字符不能与数字1和0分辨。试着在使用‘l’时用‘L’代替。
模块名 模块应该是不含下划线的,简短的,小写的名字。因为模块名被映射到文件名,有些文件系统大小写不敏感并且截短长名字,模块名被选为相当短是重要的,这在Unix上不是问题,但当代码传到Mac或Windows上就可能是个问题了。
当用C或C++编写的扩展模块有一个伴随Python模块提供高层(例如进一步的面向对象)接口时,C/C++模块有下划线前导(如:_socket)。Python包应该是不含下划线的,简短的,全小写的名字。
类名 几乎不出意料,类名使用CapWords约定。内部使用的类外加一个前导下划线。
异常名 如果模块对所有情况定义了单个异常,它通常被叫做"error"或"Error"。似乎内建(扩展)的模块使用"error"(例如:os.error),而Python模块通常用"Error" (例如:xdrlib.Error)。趋势似乎是倾向使用CapWords异常名。
全局变量名 这些约定和在函数中的一样。模块是被设计为通过"from M import *"来使用的,必须用一个下划线作全局变量(及内部函数和类)的前缀防止其被导出(exporting)。
函数名
函数名应该为小写,可能用下划线风格单词以增加可读性。mixedCase仅被允许用于这种风格已经占优势的上下文(如:threading.py),以便保持向后兼容。
方法名和实例变量
这段大体上和函数相同:通常使用小写单词,必要时用下划线分隔增加可读性。仅为不打算作为类的公共界面的内部方法和实例使用一个前导下划线,Python不强制要求这样:它取决于程序员是否遵守这个约定。
使用两个前导下划线以表示类私有的名字,Python将这些名字和类名连接在一起:
如果类Foo有一个属性名为_a,它不能以Foo._a访问。(固执的用户还是可以通过Foo._Foo__a得到访问权。)
通常双前导下划线仅被用于避免含子类的类中的属性名的名字冲突。
继承的设计
始终要确定一个类中的方法和实例变量是否要被公开。通常,永远不要将数据变量公开,除非你实现的本质上只是记录,人们几乎总是更喜欢代之给出一个函数作为类的界面
同样,确定你的属性是否应为私有的。私有和非私有的区别在于模板将永远不会对原有的类(导出类)有效,而后者可以。你应该在大脑中就用继承设计好了你的类,私有属性必须有两个前导下划线,无后置下划线,非公有属性必须有一个前导下划线,无后置下划线,公共属性没有前导和后置下划线,除非它们与保留字冲突,在此情况下,单个后置下划线比前置或混乱的拼写要好,例如:class_优于class。
最后一点有些争议:如果相比class_你更喜欢class,那么这只是一致性问题。
设计建议
单个元素(singletons)的比较,如None 应该永远用:‘is’或‘is not’来做。当你本意是"if x is not None"时,对写成"if x"要小心。例如当你测试一个默认为None的变量或参数是否被设置为其它值时,这个值也许在布尔上下文(Boolean context)中是false!
基于类的异常总是好过基于字符串的异常。模块和包应该定义它们自己的域内特定的基异常类,基类应该是内建的Exception类的子类。还始终包含一个类的文档字符串。例如:
class MessageError(Exception):
"""Base class for errors in the email package。"""
使用字符串方法(methods)代替字符串模块,除非必须向后兼容Python 2.0以前的版本。字符串方法总是非常快,而且和unicode字符串共用同样的API(应用程序接口)在检查前缀或后缀时避免对字符串进行切片。用startswith()和endswith()代替,因为它们是明确的并且错误更少。例如:
No : if foo[:3] == 'bar':
Yes: if foo.startswith('bar'):
例外是如果你的代码必须工作在Python 1.5.2 (但是我们希望它不会发生!),对象类型的比较应该始终用isinstance()代替直接比较类型,例如:
No: if type(obj) is type(1):
Yes: if isinstance(obj, int):
对序列,(字符串,列表,元组),使用空列表是false这个事实,因此"if not seq"或"if seq"比"if len(seq)"或"if not len(seq)"好。书写字符串文字时不要依赖于有意义的后置空格。这种后置空格在视觉上是不可辨别的,并且有些编辑器会将它们修整掉。不要用==来比较布尔型的值以确定是True或False
No : if greeting == True:
Yes: if greeting:
八、Shell和Python速度测试
下面是用shell和python分别创建10000个目录的脚本,分别用time测试运行时间
[root@vmware1 test]# cat a.py
#!/usr/bin/env python3.8
#coding=utf-8
import os
for i in range(10000):
dirname = "dir"+str(i)
os.mkdir(dirname)
[root@vmware1 test]# cat a.sh
#!/bin/bash
for i in {1..10000}
do
mkdir dir$i
done
1.编译 解释型
静态 动态
2.guido
3.CPython是标准Python 是我们平时用的python