浅谈python,c,java,优劣,语言高低与效率相反的不变规律
很少写关于学习计算机语言的普及型文章,但鉴于很多朋友在微博上询问我,关于python,java谁更好的问题,我觉得初学的朋友们,首先要明白一个不变的规律。那就是,所有的语言,最终都要转换为机器语言,语言越低级,越接近机器,越高级越接近人类,而开发效率,跟运行效率之间成反比的矛盾,就是编程语言,永远不变的规律之一。
先总结一句,Python只是自然进化了一级的Basic而已,远远谈不上是深思熟虑设计而成的语言。对于python这样的基础型入门级语言,因为简单易学,开发速度快,但适用范围却仅仅局限于一些非专业的入门级朋友,用来写一些标新立异的玩具程序。对于开发这些极小的程序来说,选择使用Python确实比其他语言更节省时间,这个我们必须要承认,但因此而产生的运行效率极其低下,也决定了它的应用范围仅仅适合于非专业入门级的特性。对于大规模的,所有参与的程序员都需要互相沟通的,中小型以上的普通系统工程项目来说,谈到python的话,就未免过于儿戏了。
但在讨论这个问题之前,首先我们要明白的是,一个语言的诞生,并不是为了满足所有需求,而是为了有针对性的解决某些领域,某些特定环境下,出现的某些问题的。单就语言来讲,它们本身是没有优劣之分的,只有适用环境的不同。就像如果你把python看做一个普通脚本语言,用IDA逆向分析的时候,python的作用就是自动化分析。如果你写了一个框架,那么python也可以作为模块的一个插件。你写你的框架,而这个模块可以让别人用python来写,即不冲突,也利于扩展,团队之间协作或许也更为方便。
而谈到很多朋友在讨论的,关于python是不是有设计缺陷的问题?我个人觉得,这个问题,就像讨论用铁锤剪脚指甲,有些朋友说,铁锤是有设计缺陷的,因为我尝试用铁锤去剪指甲,已经弄坏了我的两个脚趾头。
1、难易度比对。python远远简单于java。
2、开发速度比对。Python比java相对更快。
3、运行速度比对。java远优于标准python,pypy和cython拥有可以尝试追赶java的潜质,但两者却都还没有成熟到,可以单独做项目的程度。
4、可用资源比对。java取之不尽,而python相对极少,尤其是中文方面的资源。
5、稳定程度。python各版本存在相互不兼容问题,造成了一定程度上的混乱,以及大批类库失效。java由于有大型企业和大量技术人才在背后支持,所以稳定得多。
6、开源程度。python从一开始就是完全开源的。而Java由sun开发,有GUN的Openjdk等可用,所以这方面都不用担心。
7、编译还是解释。两者都是解释型。
对于我个人而言,C好比手动挡车(编译型语言),java和python(解释型语言)好比自动档车。跑的最快,操控最好的车,必然都是手动档。但是对开不好车的,入门级的朋友来说,开自动档可能就反而更快些。
谈到选择编程语言,我们需要“先确定你的需求”,不要由语言的简单还是复杂程度去决定。只有能够编写真正适合你的,对你来说最能满足你的特定需求的有用代码,才是最大的成功。
那么java和python分别适用于什么样的环境呢。作为一个资深程序员,就我的经验来讲,最著名,能久经考验的普通应用程序,基本都是c++写的。例如emule,7-zip,WinSCP,FileZilla等等等。其中一部分,由java开发,例如最有名的OpenOffice。而使用python写的却极少,如Pidgin。
就我个人而言,开发语言(按开发程序的多少)排行榜如下:
# Java
# C++
# PHP
# C
# C#
# Python
# JavaScript
# Perl
# Unix Shell
# Delphi/Kylix
# Visual Basic
# Visual Basic .NET
很多框架和类库也和应用软件一样在这个列表里,因此是比较公平的。
由此可以看出,java不管在GNU还是商业领域,都是应用最广的语言。C主要用于构建系统底层。c++和java用于构建中间应用层。如果资源足够,那么会选择c++开发,以求运行速度,否则会用java开发,以求开发速度。而与前者相比,python最受争议的,就是它的运行效能和速度。纯python比java慢得太多,而且背后也缺乏商业支持,稳定性方面备受诟病。到目前为止,python在商业层次上,仅仅只能作为一种胶水语言,用于粘合其他语言(主要是c/c++)的类库。在GNU领域,主要局限于极小规模的应用和个人化应用。以及逆向工程(hacker)应用。
那么为什么java在服务器端被大量应用,在客户端用的却比较少呢。难道服务器端用到的计算量反而少么?就我个人的经验来讲,这说明对比c++,java的速度还是可以接受的。而无法被接受的是JRE平台,以及JRE平台启动时卡的那一会儿。对于这个问题,我曾经有一段时间,因此认为java写的程序性能低下。
通常来说,追捧python的用户,常常挂在嘴上的一点是:python并不慢,因为python运行时调用了大量c库,而c是很快的。反过来想想,这不是正反映了其胶水语言的事实吗?任何一种语言都可以调用c库,因此这种比较是毫无价值的。假如一个库完全由python独立完成,那么它的运行效率将惨不忍睹。编程能总是用别人的库吗?
下面说一下Python编程语言目前在使用中,新手经常容易遇到的各种问题。下面我们就详细的看看。最近我一直在看一个,基于wxPython的GUI应用程序代码,大概45.5KLOC左右,而且还不包括它所用到的库(如Twisted)。
就这个代码来看,应该是由那些对Python比较生疏的,Java的开发者写的,所以它存在很严重的性能问题(如三十秒的启动时间)。在检查代码的时候,我发现他们写了很多在Java中能讲得通,但是对Python编程语言来说,却很难接受的东西。因为在Python中,有更方便的方法去完成同样的目标,那么这种写法,就让我们怀疑在这个case中,使用Python的必要性。
总体来看,最令人难过的,是他们的事倍功半。下面,让我们讲一讲为什么会出现以上的一些常见问题:
1、Java中的静态方法不能翻译成Python的类方法。当然,它多多少少也能产生同样的效果,但类方法的目的,实际上是做一些通常在Java中做不到的事情(如继承一个非默认的默认函数)。Java静态方法惯用的翻译,通常是翻译成一个模块级的函数,而不是一个类方法或静态方法。(并且静态常量应该翻译成模块级常量。)
这不是性能上的问题,但是一个Python程序员,如果想调用Foo.someMethod,他如果被迫采用像Java中Foo.Foo.someMethod的方式去做的话,那么最后的结果就是,他会被逼疯。在这个环节,需要注意的一点是:调用一个类方法,需要一个额外的存储空间,而调用静态方法或函数就不需要这样。
另外,这些Foo.Bar.Baz的属性链也不是自己就能数出来的。在Java中,这些带点的名称是由编译器来查找的,运行的时候并不会去考虑一共有多少。而在Python中,查找的过程是在运行时进行的,所以要包括每个点。(在Python中,要记住一点,"平铺的结构比嵌套的要好",尽管相对于从性能方面来说,可能它更多涉及的是"可读性"和"简单要比复杂好"。)
2、要使用switch语句吗?Python编程语言将是一个哈希表,而不是一堆if-then语句。要使用在Java中不是switch的语句,而且还有字符串参与了的一堆if-then语句吗?遗憾的是,它将仍然是一个哈希表。CPython字典是我们所了解的领域中,被认为性能最佳的哈希表之一。你所要明白的是,你所写的代码不会比这个更好了。
3、XML不是答案,它也不是一个问题。现在用正则表达式来解释Jamie Zawinski,当一部分人遇到问题的时候会想,这里是不是需要用到XML呢?那么这里有两个问题。相对于Java代码,XML是灵活而有弹性的。但比起Python的代码来说,XML就是一个累赘。在Python中,XML是用来协同工作的,而不是你的核心功能。在Java中,XML可能是你的救世主,因为它让你实现了特定领域的语言,并且不用编码,就能提高你的应用程序适应性。在Java中,避免编码是一个很大的优势,因为编码意味着重新编译。但在Python中,通常是写代码比写XML更简单,而Python处理代码的速度,要比处理XML快很多很多。
如果你是一个Java程序员,你并不能利用本能和直觉,来考虑是否需要在你的Python核心应用中,使用XML作为一部分。如果你不是因为信息交互的原因,去实现一个已经存在的XML标准,或是建立某种输入、输出格式,或者建立某种XML编辑器或处理工具,那么请不要这样做,最好是连想都不要这样去想。因为丢掉XML模式,才能把你解放出来。如果你的应用程序或者平台,要被Python编程语言开发者使用,那么他们只会感谢你,没有在他们的工作中,添加使用XML的负担。
4、尽量不要使用Getter和setter。Python编程语言对象不是Java Bean。因此尽量不要去写getter和setter,而是把它们内置在“属性”里。除非你需要比一个简单访问更复杂的功能(一般情况下并不多见),除此之外,都请尽量不要去写getter和setter。因为它们极其消耗CPU宝贵的资源,更为重要是,它浪费了程序员宝贵的时间。这个问题,不仅仅对于写代码和测试的朋友,对于那些要去阅读和理解它们的人,同样如此。
在Java中,你必须使用getter和setter,因为公共字段不允许你以后改变想法时,再去使用getter和setter。而在Python中,这样做是很傻的,因为你完全能够以一个普通特性开始,并可以在任何时候改变你的想法,而不用影响到这个类的任何客户。所以在Python中,尽量不要去使用Getter和setter。
5、代码重复在Java中通常来说就是一场不可避免的灾祸,你必须经常反复地写同一个方法,而只有一点点的变化(通常是因为静态类型的约束)。在Python中,这样做是没有必要的,也是不值得的(除了极少数特定场合,需要内联一些要求性能的函数)。如果你发现自己一遍遍的在写着同样的代码,而且变化很少,那么你就要开始注意了。
6、基于众所周知的理由,Java的运行效率远高于Python,而Python的突出优势就是易于学习和节省时间。所以如果你在使用Python编程语言时,并不能感到比使用Java节省了时间,那么你就需要好好的想一想,我使用Python的目的是什么?我到底是否根据现有的工作特性和环境需求,选择了正确的语言?要知道,很多时候,并不是选择编程语言的问题,出现问题的,往往是,去选择语言的人。
最后,仅以这句话初学者,与初学者共勉:“What Doesn't Kill You Makes You Stronger.”