如何为使用Python语言而辩论
最近我写了一篇关于我为什么不担心Python流失用户的文章。几分钟之后有人问我Python的用法(usage),而这篇文章没有提及,但却是一个让人深思的问题。我们看到,使用Python的用户很可能在未来保持高位,但是Python是否会被用到尽可能多的项目中是不能保证的;用户(users)数目很多而且稳定,但是项目中Python的用处(use)并不确定。
这篇文章的用意是帮助表明Python仍然对大多数软件项目是切实可行的。我不担心把Python推销给反对其他动态语言(如Ruby)的人,因为我认为这些争论与个人喜好有关。这篇文章是讲给那些推销静态类型语言的人。具体上,这篇文章是针对Go的,但也可以是其他任何静态类型语言。
“为什么Go?”,你可能会问。因为Go实际上在获取Python的用户。当2003到2005年间Python的增长曲线是个曲棍球棒时,Python还不是被推下山巅的王者,而是个弱者。传统上,Python从Java之类的语言阵营中获得用户,并且留住了他们(我不想谈C++用户,因为通常他们有严格的性能需求,需要一个系统语言,或者是性能成瘾者,并且需要好好恢复)。但是Go的情况不太一样。如今Python是使用最多的语言之一,而不再是弱者了。一旦在静态类型语言社区中出现一门语言,它的生产效率/性能的取舍相当好,那便足以说服一些Python的程序员选择Go而不再是Python了。
如今的Go
首先我应该说,Go是目前我第二喜欢的语言。如果今天我要启动一个项目,但不能说服人们使用Python,那我会提议使用Go。不要误解我在本文中说Go是门不好的语言。这篇文章的要点是说服其他人,Python是生产率/性能取舍游戏中Go之外切实可行的替代方案,而不是表达Go是门不好的语言。认为这篇文章是反Go的,那就是你的个人想法,而且不应该这样认为。
我应该说,我偶尔在工作中使用Go,并有点想关注这门语言的社区。既然我不能仅凭想象就成为Go专家,但这番话并不是仅从文档或者博客中提取出来的。但是由于我是Python开发团队的一份子,无论我如何试图表现得公平,固有的偏见某种程度上还是有的。
那么,带着这些警告,我们来看下Go提供给开发者什么。
生产率
我看待Go的方式是,使用你最喜欢的编程语言,移除那些难于加速生产率的特性,就是Go。静态类型的影响被降到最小,因为通常只有在API边界时你才会面对它。结构类型同样使事情变得简单(把它认为是鸭子类型)。语法并不笨拙(虽然它使用了花括号)。不要认为Go是C/C++去掉不安全的特性,加上生产率更高的东西,不然你会很失望(比如,“为什么我不能使用make()内置函数,也不能像map类型一样对返回值进行计数”,这种看待Go的方式是错误的;这就是为什么C++开发者没有转到Go的原因)。快速编译也使开发周期更像一个动态语言,而不是一个需要编译的语言。而且事实上有些人喜欢没有异常机制带来的冗长,因为这促使你处理每种异常情形而不是(意外地)忽略它们(这是贯穿Go初始系统语言设计的实例)。还有,这门语言本身相当短小易记,并有严格的前向兼容性要求(forward-compatibility requirements)(你不可能更快地获得泛型),大体上使用Go来编码是件很愉快的事情。
由于是静态类型,Go可以很容易地获得工具支持(它对之前以此为设计目标的语言也有帮助)。Go确保核心工具跟随Go本身提供,也是明智之举。go fmt强制执行Go风格的规则,并允许通过用户自定义的规则来重构代码(“采用制表符缩进”不再是问题,因为这意味着你可以随心所欲地设置编辑器来代表制表符,然后go fmt将其转换为普通制表符以适用VCS)。go fix会更新代码以跟最新发布的版本保持一致。go get获取依赖并安装。
Go最后一个生产率功能是它静态编译所有东西,使部署更简单。如果你使用容器来开发和部署,这也不算什么。只有当你发布单个文件的命令行工具,而不是一组依赖和你自己的代码时,这才算得上事。
性能
就性能来说,Go做的很好。很难指出任何基准能准确的证明Go总是最快的选择,甚至计算机语言基准游戏中一些基准证明CPython 3是最快的。但是通常情况下可以认为对于你的任何工作来说Go已经足够快了。
Go真正出色的地方是并发性(concurrency) 。要注意并发代码并不是通常误解的并行(parallelized)代码; 并发代码仍然可以是单线程的,仅仅在任务切换方面更加简单/出色。Go通过使用goroutine使连续并发的代码执行起来绝对的简单。如果你不想使用共享内存的方式(虽然也同样支持),该语言提供的通信管道允许以非常简洁的消息传递方式进行并发编程。将所有特征整合进此语言中成为尽可能使用该语言开发并发代码的又一原因。换句话说,Go程序运行很快,该语言尽力使你在合理的方式上获得该效果。
如今的Python
如果顺利的话我已经让你相信Go是一种优秀的编程语言,除非因为其他原因,一些人不会认为我在整篇文章对Go的描述很糟糕。现在我们讨论一下Python的生产率/性能是怎么样的。
生产率
首先也是最重要的,Python非常容易学习。这也是为什么在当前高评价的美国大学中将Python作为首选的教学语言 。这相当于该语言拥有成熟稳定的新程序员的来源以及更容易培训其他程序员。 我想,要说服别人只用几行Python代码就会完成很多工作这并不难(Go/Python 3比较 显示Python每次都比Go使用更少的代码完成相同的工作)。所以我会坚持认为使用Python会更高产,即使和Go相比,这不会有人反对。
通常大家反对Python的地方是在工具支持方面。但是如果你注意到我指出的Go相关的支持工具,fmt, fix, 和 get, Python社区也有对等的工具。对遵循PEP 8的风格格式化(style formating), 可以在提交检查时使用pep8,或者如果想要更多go fmt风格的自动重写可以使用autopep8。对用于重构的go fix或go fmt,你可以说2to3也可以完成同样的功能。对于go get, Python有pip。我们有venv/virtualenv或cx_Freeze这样的代码冻结工具(跟其他一样,位于容器之上?on top of containerization like anything else),而不是静态编译的二进制包。甚至有贯穿项目的代码分析工具如pylint。说Python因为缺少工具支持而不能用于大型项目,这种观点对我来说是很肤浅的。
如果说有哪方面Python完全做的好,那就一定是它丰富的第三方扩展库和相应的工具可供使用,就像在PyPI上面看到的那样(我相信肯定有人忍不住要争论说,“并不是所有的第三方库都能够在Python3上面运行啊”,事实确实如此,然而,这些第三方扩展库对Python3的支持已经相当好了,而且还在继续改善中,所以我不会太在意这个争论,另外,你可以同时使用Python2/3两个版本进行编码,不需要关心针对哪个版本)。看一下godoc.org,上面显示Go也并不缺少社区支持,Pytho之所以能够拥有更多可用的第三方库仅仅是因为它的年龄,这个状态也会继续持续。
性能