10 评论

为什么俺推荐 Python[2]:作为动态语言的 Python

  上一篇帖子介绍了脚本语言的优缺点,然后又拿 Python 和其它脚本语言PK了一下。今天主要是忽悠一下动态语言,捎带忽悠一下 Python。如果你看完本贴,觉得动态语言不错,那俺建议你从 Python 开始入手。


★动态语言扫盲


  考虑到还有很多同学对动态语言了解不深入,有必要先来普及一下它的基本常识。已经了解的同学,请略过本节。
  通俗地说:能够在运行时修改自身程序结构的语言,就属于动态语言。那怎样才算是“运行时修改自身程序结构”捏?比如下面这几个例子都 算:在【运行时】给某个类增加成员函数及成员变量;在【运行时】改变某个类的父类;在【运行时】创建出某个函数......
  从这些例子,你应该对动态语言有一个初步的感觉了吧?毕竟传统的静态语言(比如C、C++、Java),是很难达到这些效果滴。
  另外,有个误区需要澄清一下。很多同学以为脚本语言也就是动态语言。其实两者是不等价滴——虽然两者有很大的交集。比如 C# 在4.0之后,就可以算是动态语言了,但它不能算是脚本语言;另外,有很多 Shell 脚本语言(比如 DOS & Windows 下的 bat),不能算是动态语言。
  关于动态语言更深入的介绍,大伙儿可以看“这里”。


★为啥要学习动态语言?


  扫盲之后,就该来说一下,学习动态语言的动机了。搞明白动机,学起来才有干劲嘛 :-)

◇顺应大趋势


  假如你经常关注 TIOBE 的排名,那你应该能察觉出来,动态语言近两年的发展势头比较迅猛(在 Top10 里面,至少占了半壁江山)。这能从某个侧面反映出动态语言的影响力在扩大。
  假使你不相信 TIOBE 的排名,俺再举一个例子。两大开发阵营(Java 和 dotNet)最近几年也加大了对动态语言的支持力度。比如,dotNet 的 CLR 加入了对IronPythonIronRuby 的支持;Sun 当然也不甘示弱,JVM 也开始支持 GroovyJRuby 等语言。
  俺费了这许多口水,列位看官应该明白动态语言是大势所趋吧。在这动态语言大行其道的日子里,你如果连一门动态语言都没搞懂,那出门都不好意思跟人打招呼。
  不过,话又说回来,静态语言也是不会消亡滴。毕竟,静态语言有自己的优势(比如严谨、性能)。长期来说,必定是动态语言和静态语言并存。各自弥补对方的缺点。

◇了解新思维、新理念


  学习一门动态语言还有一个好处:有很多时候,多学习一门语言,并不一定是为了在工作中用它,而是为了学习新的思维方式、体会新的理念。比如俺就曾经花时间去看 Prolog,但是俺在工作中,从来不需要用到它。(以后有空的话,俺会介绍一下这玩意儿)
  由于动态语言可以在运行时修改自身结构,因此就会产生很多静态语言所没有编程范式和手法(比如 evalMixin)。如果你以前只使用静态语言,那你在学习了动态语言之后,多半会从它身上领略到很多新的思想和理念。
  (关于 eval 的招数,俺后来写了一篇《再举几个动态语言 eval 手法的例子》)

◇能够化繁为简


  可能有些同学觉得,前面说的都有些务虚,那咱再来说点具体实在的。大牛 Edsger Dijkstra(图灵奖得主)曾经说过:编程的艺术就是处理复杂性的艺术。咱们来看看,动态语言是如何处理复杂问题滴。
  假设要你实现一个函数,用来完成两个数的“某种运算”,具体的运算类型作为函数的参数传入,然后该函数返回运算结果。比如:
Foo("+", 2, 4) # 返回 6
Foo("*", 3, 5) # 返回 15
  对于上述需求,你会如何实现捏?
  请先暗自盘算一柱香的功夫,然后再往下看。

......
Thinking
......

  如果你用静态语言(比如 C、C++、Java)来实现,你可能会在函数内使用一个 switch,根据不同的运算符,进行计算,然后返回计算结果。
  对于某些比较 OO 的语言(例如 C++、Java),你或许还会抽象出一个运算的接口类(纯虚类),然后分别派生出若干个不同的计算类(比如加法类、乘法类),看起来似乎比 switch 要优雅一些。
  当然,用静态语言还有其它一些玩法,但是代码量都不会少。具体详情可以看很早以前的一个老故事:《4个程序员的一天》。(其实俺这个例子的灵感就是从那个老故事剽窃滴)
  现在,咱们来看看 Python 是如何【优雅地】实现该需求滴。用 Python 只需要【两行代码】即可。请看:
def Foo(op, n1, n2) :
    return eval( "%d %s %d" % (n1, op, n2) )
  不懂 Python 的同学可能要问了,这两行代码是啥子意思呀?
  其实,第一行代码只不过是定义了一个函数头,第2行代码才是精华。这里面利用了动态语言常见的 eval 手法(具体参见“这里”)。在 python 里面,内置的 eval 函数可以把某个字符串当成一个表达式,并对其求值。而语句 "%d %s %d" % (n1, op, n2) 只不过格式化出一个表达式的字符串。
  顺便再插一句,Python 还有一个 exec 的内置函数,可以把一段 Python 源代码作为字符串参数传递给它,让该函数去执行。两个函数结合起来,就能玩出很多花样。具体的花样可以参见“这篇博文”。


★为什么是 Python?


  说了动态语言的种种好话,有同学会问了,动态语言有很多种,为啥非要学习 Python 捏?
  首先,俺在本系列第1篇帖子,已经对比过 Python 和另外几种脚本语言。那几种“脚本语言”碰巧也是知名的“动态语言”。Python 相对于他们的优势,此处就不再重复啰嗦了。
  其次,单就语法本身而言,Python 的语法对动态性的支持是很优雅、很简洁滴。通过刚才那个 eval 小例子,大伙应该已经看出来了。为了更形象一点,咱拿前面提到的 Mixin 来 Show 一下 Python 的语法是如何的简洁。
  通俗地说,Mixin 手法需要在【运行时】给某个类增加基类(也就是父类)。对于 Python 而言,每一个类都有一个内置属性 __bases__,里面包含这个类【当前】的所有基类。假如要在【运行时】增加基类,只需操作 __bases__ 这个属性即可。
  比如有一个类 A 和类 B。如果要在运行时把 B 加为 A 的父类,可以用如下语句:
A.__bases__ += (B,)
  是不是也很简洁,而且可读性也不差?相比而言,有些动态语言(比如 JavaScript),要实现类似的效果,代码就相对复杂了。
  由于 Mixin 不是今天的重点,就不再深入展开了。


★总结


  最后,来个总结发言:如果你之前没有接触过动态语言,建议去学习一下;如果你已经打定主意要学,Python 是比较好的候选者。
  好了,今天就聊到这里。下一个帖子,咱们来讲讲 Python 作为一个纯粹的面向对象语言,有些啥特色。


回到本系列的目录
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者编程随想和本文原始地址:
https://program-think.blogspot.com/2009/08/why-choose-python-2-dynamic.html

10 条评论

  1. >有些动态语言(比如JavaScript),要实现类似的效果,代码就相对复杂了。

    JavaScript可能不算复杂,如果您用过jQuery,或者ExtJS,这些框架基本都有 extend 的方法,相当灵活。

    回复删除
  2. 一如既往的来学习。感谢楼主分享这么多宝贵的经验。

    回复删除
  3. 嘿嘿,google收实习生写明说要python熟悉啊,看来我一定要掌握这门语言啦,不过我是菜鸟,请问一下,一个毫无语言基础的人应该从什么语言学起呢?我看过了C语言的概述,不过看不太懂,我也没看下去,高中的时候学过VB,感觉VB还挺容易的,我应该从VB学起吗?

    回复删除
  4. 楼上的同学:
    建议不要从VB开始学起。俺不看好VB的前途,且VB语言的语法比较土 :)
    其实Python作为初学者的编程语言,是很合适的。俺尝试过在公司推广,很多没有编程基础的测试人员,都可以快速上手。

    回复删除
  5. 最近也在看Python

    俺C出生的人,看Python怎么看怎么怪。。不过看了一会,觉得好像挺handy的一个东西,少了很多条条框框的语法和结构

    另外lsdls,我也不推荐VB。。。其实C学起来不比VB难啊,学VB还不如学C#

    回复删除
  6. 此评论已被作者删除。

    回复删除
  7. 在这里给编程君留个言,希望编程君能看见吧!
    前几天,在gmail里面给我推送了一个邮件,标题里面说了编程君近期推荐的一个vpn。
    当然,我毫不犹豫的就来到了编程君的blog里面来看那个vpn的内容,再于是乎,便一发不可收拾,从头到尾翻看了大量的编程君的blog。
    我总结开来,四个字:受益匪浅
    今天当然一如既往的来看编程君其它的blog,这篇里面的一句话,对我很是受启发:“有很多时候,多学习一门语言,并不一定是为了在工作中用它,而是为了学习新的思维方式、体会新的理念。”
    学习新的思维方式、体会新的理念,这句话会铭记我心的。
    编程君每篇blog里面所提及的其它相关东西,我都有去看,去学习,这两天来看君blog,着实学习了很多很多。
    感谢编程君的无私奉献吧,真心感谢。
    今后,我会多多向编程君学习相关的知识的!

    顺便说一下:编程君不建议我打印网页吧(我只供个人学习用途,不会干其它事情的),因为编程君每篇blog里面都涉及到了,很多自己之前从未有接触到的名次,所以那。我就打印了,并且加以标记,以自己之力去研究每个自己感兴趣的关键字。

    最后,还是说一句:感谢!

    回复删除
    回复
    1. 多谢捧场 :)

      打印博文网页,俺当然不介意。
      而且俺非常欢迎转载俺的博文——只要记得保留文章结尾的“版权声明”和原始网址。

      删除
  8. eval是邪恶的。。。。。动态修改类的信息,出了bug很难找。。。

    这些特点,新手大都难以正确使用,他们用的不对使得代码可读性更差隐藏bug更多,入错门了却不知道,自己还在暗自窃喜。 建议新手们阅读一些介绍这些动态特点的书籍以明确什么时候使用这些特性是合理的。
    至于书嘛,还得指望博主推荐。。。。

    回复删除
  9. 动态语言是不是更容易出现脚本注入漏洞?比方说用户上传了一个图片或者音频,却注入了一条可执行命令

    回复删除