惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
T
The Blog of Author Tim Ferriss
J
Java Code Geeks
腾讯CDC
D
Docker
G
Google Developers Blog
D
DataBreaches.Net
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
S
SegmentFault 最新的问题
The Cloudflare Blog
有赞技术团队
有赞技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
大猫的无限游戏
大猫的无限游戏
量子位
美团技术团队
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - FantasySoft

PHP菜鸟手记——如何解决无法装载动态链接库的问题 穿在身上的手机——M-Dress 团购之道——双赢才是核心 Demand Media——深谙中庸之道的新媒体 云中谁寄锦书来,盛大也! 《黑客》月刊中文版第一期正式发布,很给力!推荐围观! 比尔•盖茨:未来最好的教育来自互联网 CaptureDeviceManager.getDeviceList方法返回null对象问题探究 为了生活更美好,玩游戏吧! 三言两语话委托 IronPython Tools——为IronPython度身定做的IDE 从博客园口水仗想到的 由XML Literal引发的思考 作为.NET程序员,您需要IronPython么? 静态注册BroadcastReceiver的注销问题 大道至简——Michael看iPad 波哥大BRT带来的启示 Timberland的企业社会责任 比尔•盖茨谈教育
lambda与闭包
FantasySoft · 2010-05-03 · via 博客园 - FantasySoft

2010-05-03 16:43  FantasySoft  阅读(7368)  评论()    收藏  举报

《作为.NET程序员,您需要IronPython么?》一文中,Michael给大家介绍了IronPython的诸多优点,其中的一条就是IronPython实现闭包要比C#和VB.NET来得更为直观。在文中,针对“找出长度较短的字符串”的功能,我给出了IronPython的代码:

>>> SampleData = ["the""quick""brown""fox""jumped","over""the""lazy""dog"]
>>> maxLength = raw_input("Maximum length of string to include?"
>>> maxLength = int(maxLength)
>>> shortWords = [i for i in SampleData if len(i) <= maxLength]

这段代码的核心在于最后一个赋值语句,它是典型的列表内涵(List Comprehension)的应用。而事实上,这个赋值语句等价于以下的代码:

shortWords = filter(lambda i: len(i) <= maxLength, SampleData)

使用这样的代码也许和C#和Java的闭包-Jon谈《The Beauty of Closures》一文中C#代码具有更强的可比性,因为lambda是Python中用于定义匿名函数的关键字,而匿名函数又是实现闭包的充分条件之一(非必要条件)。在讨论闭包和lambda之前,我们先来了解一下filter函数。


filter(function, sequence)函数是Python的内建函数,我们无需引入任何的包(package)即可使用。它实现了将序列中某些符合条件的元素筛选出来的功能;它需要两个参数:第一个是函数,用于定义筛选条件;而另一个则是序列,作为被筛选的对象。Python Tutorial给出的示例代码可以帮助我们更好地理解filter这个函数。

现在,您对filter函数有一定的认识了吧?那么让我们再回到上述的赋值语句。lambda定义了一个匿名函数,它返回了一个布尔值:True或者False,而判断条件则是:参数的长度小于或者等于maxLenth。在这里,lambda充其量只是一个语法糖,让代码更加易读,并没有体现出它与闭包的关系。说到这里,您一定会问:到底什么是闭包呢?从定义上来说:闭包就是由函数与其相关的引用环境组合而成的实体。如果一门语言很好地支持闭包,那么它需要具备以下条件:
    • 函数是语言的一等公民,它不从属于其它任何对象,可以作为方法的返回值;
    • 函数可以嵌套定义;
    • 可以捕获引用环境,并把引用环境和函数代码组成一个可调用的实体;
    • 允许定义匿名函数。
 基于上述条件的第三点,我们可以将上述代码改写为如下形式:

>>> SampleData = ["the""quick""brown""fox""jumped","over""the""lazy""dog"]
>>> def filterFunc(maxLength): 
...     
return lambda i: len(i) <= maxLength
>>> maxLength = raw_input("Maximum length of string to include?"
>>> maxLength = int(maxLength)
>>> shortWords = filter(filterFunc(maxLength), SampleData)

我们回头对照一下上述的条件,filterFunc不正是闭包的最好体现么?也许您会觉得我有点画蛇添足,多此一举,但是,我们确实拥有了一个极具灵活性的可调用实体。如果要筛选出最大长度为4的单词,我们可以这么做:

fourLetter = filter(filterFunc(4), SampleData)

如果要筛选出最大长度为3的单词,我们又可以这么做:

threeLetter = filter(filterFunc(3), SampleData)

我们回想一下面向对象编程当中的函数,它的定义是固定的,不会在运行时发生变化。而闭包则不同,它会根据不同的引用环境发生变化,从而返回不同的函数实例。因此,我会把闭包等同于返回值是函数的函数,而lambda的存在可以让返回的函数定义得到简化。更多有关闭包的介绍,请参考园子里的季方亮同学的文章——《函数编程之闭包漫谈(Closure)》;有关lambda的介绍,则请参考CoderZh同学的文章——《Python天天美味(35) - 细品lambda》

最后,也许有朋友会问:我们为什么需要lambda和闭包呢?这是为了将side-effect降至最低,也就是将变量从我们代码当中剔除!我想您一定会对此很惊讶,但这是事实,最纯粹的函数式编程是只有定义的。基于此,最开始的代码还能演变成如下所示:

>>> SampleData = ["the""quick""brown""fox""jumped","over""the""lazy""dog"]
>>> raw_input("Maximum length of string to include?")
>>> print(filter(lambda i:len(i) <= int(_), SampleData))

对编程范式感兴趣的朋友,可以参考我的文章:《说的都是概念——有关编程范式》