posts - 256, comments - 1319, trackbacks - 41, articles - 8
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

        在Python中,lambda是一个有趣的关键字,它用于定义简单的匿名函数。匿名函数的概念,是指没有与特定变量绑定的函数。也就是除了定义的那一刻可以引用该函数之外,你无法通过任何方式再次引用它了。这类似于我们熟知的立即数,因此我给由lambda语法定义的匿名函数起了个新名字:立即函数。存在即是真理,Python中引入了lambda语法,引入了匿名函数的概念,它所坚持的真理又是什么呢?
       
假设我们已经有了这样一个函数定义:

def func(x, y):
    
print x, y


在我们调用一个函数或者说一个方法的时候,调用方式可以是这样的:

a, b = "Hello"1
func(a, b)


也可以是这样的:

func("Hello"1)


那么这两种调用方式有什么不同呢?是的,这个例子真的太简单了,以至于你会马上发现它们之间的
不同,也正是由于它太简单了,你也会觉得比较两者的区别简直就是在钻牛角尖。别着急,这简单的背后隐含的内容可不简单。很明显,第一种调用方式比第二种多出了两个变量,也多出两个赋值的语句(statement),在函数调用的时候通过变量引用具体的值;而第二种方式则是直接以具体的值作为参数,没有变量与这些值绑定。如果"Hello"和1使用的次数不多,那么第二种直接的调用方式会更为高效,毕竟在某个(可能会是全局)范围内,你不需要将"Hello"和1绑定到某个变量,所开辟的内存空间也可以及早地被回收,更重要的是减少不必要的错误!在一个复杂的应用程序中,变量就如同于一个状态机,变量的改变有些时候是程序能够执行的驱动力,有时候则是程序正常执行的绊脚石。作为程序员,我们需要跟踪并熟知这些变量的状态(当前值是什么),否则就很容易编写出错误的程序,而在现实中,大多数程序错误都会来源于你所使用的变量值与你所预期的不一致。说到这里,你应该会想起使用Debugger调试程序的痛苦经历,也会想起为一些让人迷惑的变量增加一个个Watch以便确定它们某个状态值的繁琐过程,我想,你也应该明白“减少不必要的错误”指的是什么了:减少变量定义,减少statement,也就减少了side-effect,最终减少了程序员的负担。在这里,我们引出了另外一个需要关注的新概念——side-effect
        其实side-effect的含义在上面的文字中已经隐约提到了(上文红色字的部分),以下是引用自
Wikipedia的定义:In computer science, a function is said to produce a side-effect if it modifies some state other than its return value。side-effect是一把双刃剑,不同的语言对它有着不同的态度:Imperative programming Language(命令式编程语言,譬如C++、C#和汇编)是充分利用了side-effect来驱动程序的运行;而Declarative programming Language(声明式编程语言,譬如SQL和Haskell。Functional programming Language是它的重要组成部分)则是在最大程度上限制side-effect。这里又是三个新的概念,大家从给出例子中应该可以对这两种语言有一个感性的认识,我就不做解释了,以上给出的链接提供了更为详细的内容。
        对于命令式编程语言,大家肯定是最为熟悉的,因为我敢说99%的程序员都在使用命令式编程语言。
那么你对以上提到的利用side-effect驱动程序的运行的理解又有多少呢?其实,这并非是一个深奥的问题,因为这在程序中几乎无所不在,一个很简单的例子就是循环中用于条件判断的变量,如果我们恰当地定义了循环的起始和终止条件,那么我们就会得到一个预期的有限次数的循环,一旦定义错误,死循环也就不可避免了。而对于声明式编程而言,大家可能就相对了解得比较少了,可能对Functional Programming Language了解得更多一些。Functional Programming Language所关注的是定义,也就是程序需要处理的内容,而不是如何去处理,关注的是what,而非how。在最为纯粹的Functional Programming中,定义就是程序的全部。说到这里,你或许会像我第一次接触Functional Programming的时候一样,觉得很诧异,光有定义的程序能够被执行吗?想想一条SQL的执行,解答疑惑也就有了线索。是的,当定义碰上分析定义的Engine,定义也就有了生命。限制side-effect是Functional Programming Language的重要特性之一,而限制side-effect的最简单手段就是减少变量的使用,减少statement。在真正纯粹的Function Programming Language中,是不会有statement存在的。
        好了,要提到的概念都陆续登场了,最开始提到的问题还是给出答案呢。啊,你忘了是什么问题啦?
嗯,嗯,看来我真的太罗嗦了。不过,你在回头看看问题的时候,你的心里是不是也有了答案呢?
        在Python中OO机制虽然足够强大,但由于Python本身更加注重Functional Programming,function才
是名副其实的first class。Python中的function几乎无所不能,一个Python程序的功能几乎都依赖于function的定义,而function本身更是可以操作其他function,甚至还能动态生成class!然而在没有lambda之前,function是离不开def的,def就相当于function的statement,阻碍着Python充当一个纯粹Functional Programming的角色。因此,利用lambda将function平民化,让function也能像上面"Hello"和1那样自然地扮演function参数的角色,这无疑是一个漂亮的设计。依靠lambda,Python可以做到最纯粹的Functional Programming——这就是问题的答案。以下这篇文章来自著名的Charming Python系列:Functional Programming In Pytthon,它会给你更多的启示。我相信你在阅读的过程中会惊喜的发现,程序原来也可以这样写的。
         说的都是概念,看完以后可别忘了练一练。:)

Feedback

#1楼    回复  引用  查看    

2005-12-17 18:04 by dragonpig      
这个例子举的不是很好耶。
我不是很了解Python,Declarative programming中也只接触过SQL。
不过在Imperative programming中,结构化,OO都是减少side-effect的措施。

#2楼    回复  引用  查看    

2005-12-17 20:50 by idior      
Declarative programming 也不断以某种形式被引入现在的高级语言中, .net 中的attribute就是一个很好的例子.

#3楼 [楼主]   回复  引用  查看    

2005-12-18 03:06 by FantasySoft      
To dragonpig: side-effect是一把双刃剑,减少不见得是好事。至少,没有了side-effect,imperative programming赖以执行的驱动力就会消失。因此,我也不是很明白,您提到的减少side-effect的措施该如何去诠释呢?

#4楼    回复  引用  查看    

2005-12-29 20:48 by dragonpig      
@FantasySoft
你让我困惑了。请看一下自己写的“减少变量定义,减少statement,也就减少了side-effect,最终减少了程序员的负担”。是不是有些自相矛盾。
可能用“控制”一词更为妥当。von Eeumann language家族(如C)是通过side-effect工作的典范。但有些特征比如C中的全局变量(典型的side-effect)容易造成开发的混乱和维护的困难。
我原来的意思是需要对这种过度依赖side-effect进行控制。如在OOP中将状态封装于对象内部而非散布于整个系统之中,因而降低了side-effec,这t正是一种措施。

#5楼 [楼主]   回复  引用  查看    

2005-12-30 00:56 by FantasySoft      
@dragonpig: 哈哈,真的很感谢您的Comment。您说得很对,我之前的回复确实草率了。

对于side-effect的态度从来就像是一个哲学问题,支持或者反对都是有理的,也就是说当我使用Java或者C#编程的时候,我会看重side-effect有利的一面,并充分恰当的发挥它的作用。而到了使用Python的时候,我就会考虑尽量削弱它的影响。
因此当您提到减少side-effect的时候,我就跳出来为Java和C#说话了,呵呵~~


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-12-19 11:22 编辑过
 
另存  打印