语言的那点小事

这篇文章主要讲讲本人近期对编程语言的理解,对编程语言涉及到的编程方法(范式)上的差异以及产生这种差异的内在原因的理解。这次用来做示范的是当前普遍被使用的两门编程语言java、python。之所以以这两种语言作为参考,是因为这两种语言恰恰能够代表编程语言的两个主要类别,那就是以java为代表的静态语言和以python为代表的动态语言。静态语言家族包括C/C++、C#、java、go等,动态语言则包括有python、javascript、php等。从规模上可以看出,这两种类型的语言都占有着非常大的使用比例,流行程度上难分高小,应用领域都非常广泛。由于时间有限,仅就java和python两种语言作为各自的代表进行研究。有不对之处,还请不吝指教。

  • 静态语言 or 动态语言

怎么区分静态语言还是动态语言?其实很简单,先给出一个浅显易懂的判断标准:定义变量时,需要声明变量类型的是静态语言,不需要声明的则是动态语言。是不是很简单?那么有人要说了,你前面提到的C#、go语言,甚至连新版(JDK9)的java语言中都可以如示例1这样定义变量,这难道说明它们都是动态语言,而并非你之前提到的静态语言咯?

var value = 100; //示例1

确实,按照上文给出的简单方法,则C#、go语言等也许都可以划入动态语言阵营了。然而,实则不然,伴随着人们对动态特性便利性的重视,很多语言与时俱进,都引入了动态语言的部分特性,连java这种老气横秋的语言都在与时俱进:)。在此,需要给出更加准确的定义才能区分。我没有参考教科书或者任何官方解释,仅个人见解的描述。

静态语言是指在编译期能够确定变量类型的语言,而动态语言则是指在运行期间才能确定变量类型的语言。

利用这个定义就可以正确判断到底谁是静态语言,谁是动态语言了。示例1中的代码如果是C#,那么value的类型其实是在编译期确定的,这是利用编译器的类型推导能力实现的,即通过右值的类型推导出左值value的类型(有兴趣研究类型推导的同志可以关注下类型系统这个领域),所以C#还是只能归为静态语言一类。而如果示例1是javascript的代码,则value的类型是在运行期方能确定,因此javascript是动态语言。这样我们就终于能够区分清楚了。

很多同志在判断静态和动态语言的时候,经常会被另一个概念所迷惑,那就是强类型和弱类型。他们往往认为静态语言就是强类型语言,而动态语言就是弱类型语言。这是一个严重错误的认识。其实这个强弱类型和动静态是两类不相干的概念。比如作为动态语言的python是强类型的,因为python的类型不能相互隐式转换,而作为静态语言的C/C++语言则是弱类型的,因为C/C++语言允许类型进行隐式转换(如int转double)。具体哪些语言属于什么类型可以见下图(图来自网络),大家可以自己思考一下为什么java是强类型语言。

编程语言分类图
  • 用python和java编程的“感觉”

相信写过两种语言的同志们都会有各自对两类语言编程风格的独特体会,从我个人而言,概括起来,那就是:

python(代表动态语言):自由灵活,却神锋太俊,飘飘乎云端。
java(代表静态语言):严谨务实,冗长无趣,胶柱鼓瑟,自缚手脚。

java作为一门工业化级别的语言,适合团队化开发,由此诞生的各种设计模式,大大的提高了工业化生产的效率。设计模式就如同一家大企业的各种制度,一定程度的缓解了大公司体量所带来的负担。但同时也限制了员工们个人的创造力,减弱了他们认知的广度以及尝试新鲜事物的好奇心。而python的动态化特性就完全放开了各类约束,鼓励你放飞思想,写出简短精悍、富有想象力的代码。但也正是python的这种特点,造成了其不适合团队化、大规模合作的生产环境,由于缺乏编译期类型检查(虽然有扩展支持类型检查工具,用的很少),将错误推后到运行期,导致编译器工具无法对其进行静态代码检查和优化,加剧了调试和测试的需求。且风格过于灵活,需要辅之以大量的编程规范,加大了工作难度。

  • 设计模式的围城

每一个java程序员都会对设计模式津津乐道,建立在设计模式之上的各类“框架”是java生产力的重要支撑,脱离了各种方便的java框架,或许很多java程序员瞬间就会无所适从,双手一摊,表示无能为力了。可见,设计模式在java语言的应用中占有非常重要的地位。举个例子,Spring是一个家喻户晓的j2ee框架,里面最核心的依赖注入和控制反转的理念就是设计模式思想的体现。java反射的语言特性为Spring实现控制反转的技术机制,而工厂模式则为依赖注入提供了思想源泉。同理Spring对AOP的支持,则是代理模式的应用。这些一定程度上体现出了设计模式的威力。

那么python程序员需要设计模式吗? 让我们来仔细思考一下,不妨用python实现一个工厂模式和抽象工厂模式看看:

class Human:
    pass

class Woman(Human):
    pass

class Man(Human):
    def a(self):
        return 100

factory = {
    "man": Man,
    "woman": Woman,
    "human": Human
}

class Chinese:
    pass

class European:
    pass

class Dog:
    pass

class Pig:
    pass

#工厂就这么简单
man = factory["man"]()
woman = factory["woman"]()
human = factory["human"]()


manFactory = {
    "chinese": Chinese,
    "european": European
}

animalFactory = {
    "dog": Dog,
    "pig": Pig
}
    
#抽象工厂(无非就是工厂的工厂)
abstractFactory = {
    "manFactory": manFactory,
    "animalFactory": animalFactory
}

...

我们看到了动态类型的威力,自由灵活。在这个例子当中,没有涉及到java中的所谓接口、继承、实现等实现工厂模式必须的概念。其实,设计模式很大程度上是为了弥补java语言在语言动态特性不足上的缺陷,大量的设计模式相当于是给java语言打补丁。而python则在很大程度上讲设计模式的思想内置到了语言的内涵当中,这其中的二三事需要仔细体会。下面再举一个策略模式的例子(也许是个悲伤的故事):


def loveMeOrHim():
    return input("love me or him? ")

def loveMe():
    print 'love you too!'

def loveHim():
    print 'my best wishes'

def loveNoOne():
    print 'all right, we can be good friends'

def firstStrategy(*arg, **argw):
    loveMe(arg,  argw)

def secondStrategy(*arg, **argw):
    loveHim(arg, argw)

def thirdStrategy(*arg, **argw):
    loveNoOne(arg, argw)

#由于函数或类在python中都是first-class的,所以策略模式就是这么简单
def main():
    girlsWord = loveMeOrHim()
    if girlsWord == 'you':
        solver = firstStrategy
    elif girlsWord == 'him':
        solver = secondStrategy
    else:
        solver = thirdStrategy
    
    solver()

main()

为什么这里实现策略模式很简单又很直观呢?脱离了java的接口、实现、继承等概念。原因就是python语言将函数或类作为了first-class的结构,可以理解为函数和类本身就是一个值,这个值可以被传来传去,可以被当做参数赋来赋去。可以换句话说,python语言直接就内置策略模式,或者说至少内化了策略模式的思想。读者同志们如果感兴趣,可以将java常见的各种设计模式用python实现一遍,记住不要一来就设计什么接口啊、类啊,最好透过现象看本质,先抛弃各种java强加于你的思维定式,再充分利用python语言本身的特性来设计实现(熟悉python的同志都知道,用python实现个AOP又是何其的简单),如果你能够剥去浮在表面的各种尘埃,还能推陈出新,则几近道矣。

  • 结语

其实还有很多想说想写的话,但是我是一个没有耐心的人,一时心血来潮毕竟无法持久的输出,恰如王献之雪夜访友。我对编程的兴趣也是来去如风,不萦于怀的,兴尽则收,或许也是败笔之源。其实这篇文章通篇废话,俱是基础,也就供些年轻人笑读尔。回想韶华不驻,二十六载一晃即过,所见诸事本皆小道所宿尔,不提也罢,怎可谓几近道矣,羞而大笑。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343