作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明。谢谢!

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

闭包(closure)是函数式编程的重要的语法结构。函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式)。在面向过程编程中,我们见到过函数(function);在面向对象编程中,我们见过对象(object)。函数和对象的根本目的是以某种逻辑方式组织代码,并提高代码的可重复使用性(reusability)。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。

不同的语言实现闭包的方式不同。Python以函数对象为基础,为闭包这一语法结构提供支持的 (我们在特殊方法与多范式»http://www.cnblogs.com/vamei/archive/2012/11/19/2772441.html✔ 中,已经多次看到Python使用对象来实现一些特殊的语法)。Python一切皆对象,函数这一语法结构也是一个对象。在函数对象»http://www.cnblogs.com/vamei/archive/2012/07/10/2582772.html✔ 中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。

函数对象的作用域

和其他对象一样,函数对象也有其存活的范围,也就是函数对象的作用域。函数对象是使用def语句定义的,函数对象的作用域与def所在的层级相同。比如下面代码,我们在line_conf函数的隶属范围内定义的函数line,就只能在line_conf的隶属范围内调用。

def line_conf(): def line(x): return 2*x+1

print(line(5))   # within the scope

line_conf() print(line(5))       # out of the scope

line函数定义了一条直线(y = 2x + 1)。可以看到,在line_conf()中可以调用line函数,而在作用域之外调用line将会有下面的错误:

NameError: name 'line' is not defined

说明这时已经在作用域之外。

同样,如果使用lambda定义函数,那么函数对象的作用域与lambda所在的层级相同。

闭包

函数是一个对象,所以可以作为某个函数的返回结果。

def line_conf(): def line(x): return 2*x+1

return line       # return a function object my_line = line_conf() print(my_line(5))

上面的代码可以成功运行。line_conf的返回结果被赋给line对象。上面的代码将打印11。

如果line()的定义中引用了外部的变量,会发生什么呢?

def line_conf(): b = 15

def line(x): return 2*x+b return line       # return a function object

b = 5 my_line = line_conf() print(my_line(5))

我们可以看到,line定义的隶属程序块中引用了高层级的变量b,但b信息存在于line的定义之外 (b的定义并不在line的隶属程序块中)。我们称b为line的环境变量。事实上,line作为line_conf的返回值时,line中已经包括b的取值(尽管b并不隶属于line)。

上面的代码将打印25,也就是说,line所参照的b值是函数对象定义时可供参考的b值,而不是使用时的b值。

一个函数和它的环境变量合在一起,就构成了一个闭包(closure)。在Python中,所谓的闭包是一个包含有环境变量取值的函数对象。环境变量取值被保存在函数对象的__closure__属性中。比如下面的代码:

def line_conf(): b = 15

def line(x): return 2*x+b return line       # return a function object

b = 5 my_line = line_conf() print(my_line.__closure__) print(my_line.__closure__[0].cell_contents)

__closure__里包含了一个元组(tuple)。这个元组中的每个元素是cell类型的对象。我们看到第一个cell包含的就是整数15,也就是我们创建闭包时的环境变量b的取值。

下面看一个闭包的实际例子:

def line_conf(a, b): def line(x): return a*x + b return line line1 = line_conf(1, 1) line2 = line_conf(4, 5) print(line1(5), line2(5))

这个例子中,函数line与环境变量a,b构成闭包。在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个环境变量的取值,这样,我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,我们可以看到,闭包也具有提高代码可复用性的作用。

如果没有闭包,我们需要每次创建直线函数的时候同时说明a,b,x。这样,我们就需要更多的参数传递,也减少了代码的可移植性。利用闭包,我们实际上创建了泛函。line函数定义一种广泛意义的函数。这个函数的一些方面已经确定(必须是直线),但另一些方面(比如a和b参数待定)。随后,我们根据line_conf传递来的参数,通过闭包的形式,将最终函数确定下来。

闭包与并行运算

闭包有效的减少了函数所需定义的参数数目。这对于并行运算来说有重要的意义。在并行运算的环境下,我们可以让每台电脑负责一个函数,然后将一台电脑的输出和下一台电脑的输入串联起来。最终,我们像流水线一样工作,从串联的电脑集群一端输入数据,从另一端输出数据。这样的情境最适合只有一个参数输入的函数。闭包就可以实现这一目的。

并行运算正称为一个热点。这也是函数式编程又热起来的一个重要原因。函数式编程早在1950年代就已经存在,但应用并不广泛。然而,我们上面描述的流水线式的工作并行集群过程,正适合函数式编程。由于函数式编程这一天然优势,越来越多的语言也开始加入对函数式编程范式的支持。

欢迎继续阅读“Python快速教程»http://www.cnblogs.com/vamei/archive/2012/09/13/2682778.html✔”

小奋斗文章

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

python教程闭包_Python教程 闭包的特性相关推荐

  1. python装饰器与闭包_python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)。...

    转载:http://python.jobbole.com/81683/ 呵呵!作为一名教python的老师,我发现学生们基本上一开始很难搞定python的装饰器,也许因为装饰器确实很难懂.搞定装饰器需 ...

  2. python学英语视频教程_python教程(入门, 经典, 英文)

    python教程(入门, 经典, 英文) 简介:经典之作, 秒杀各种python教材, 视频制作无可挑剔, 英文讲解非常通俗流利. 即可作为python的入门教程的首选, 又是很好的英文听力催眠视频, ...

  3. python画笔宽度_python教程系列终章:画笔控制

    原标题:python教程系列终章:画笔控制 3. 画笔控制 通过前面两节的学习,大家可能会感觉到实际上的编程相当于我们手握一直笔,通过各种指令控制笔的路径. 没错,我们平时写字或画画的各种操作都能够用 ...

  4. python表白神器_python教程之抖音同款表白神器——Python让你的七夕更完美!

    又到了一年一度的七夕!大家都准备送什么给自己心仪的对象呢?今天给大家带来python教程之抖音同款表白神器--Python让你的七夕更完美! 先上效果: python表白小程序 代码: from tk ...

  5. python重复输出_Python教程第10篇: python print换行输出和python将一句话重复n次输出...

    内容提要:本篇Python教程分享了两个问题的解决方法,分别是python print换行输出和python将一句话重复n次输出. 学习到现在,我们的Python教程进入第10课的学习.刚才小编在网站 ...

  6. python 使用全局变量_Python教程之全局变量用法

    Python教程之全局变量用法 本文实例讲述了Python全局变量用法.分享给大家供大家参考,具体如下: 全局变量不符合参数传递的精神,所以,平时我很少使用,除非定义常量.今天有同事问一个关于全局变量 ...

  7. python dict遍历_Python教程:Python数据类型之字典(附学习教程)

    字典是另一种可变容器模型,且可存储任意类型对象,是除列表以外python之中最灵活的内置数据结构类型.查找速度非常快,一个元素和10W个元素没有什么区别. 堆栈的词典 字典的无序特性和创建: 列表是有 ...

  8. python 返回函数 闭包_python中闭包Closure函数作为返回值的方法示例

    前言 首先看看闭包的概念:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外 ...

  9. python教程苹果版_python教程

    https://www.xin3721.com/eschool/pythonxin3721/ 1.安装Homebrew https://brew.sh/index_zh-cn.html 2.通过bre ...

最新文章

  1. 2位图灵奖得主、7位院士等一众AI大佬云集共议数字化转型 | CNCC 2021
  2. it is important to delete your email mailbox in a frequent manner!
  3. Activity的生命周期及各生命周期方法的作用
  4. Windows 2000缓冲区溢出技术原理
  5. 技术篇-HBase Coprocessor 的实现与应用
  6. C# int转string 每三位加一个逗号
  7. 电商数据之战背后利益纠葛:触动最敏感神经
  8. 讨厌的任意门事件,删了会出系统提示:安装prosheild.msi问题,不要乱删!
  9. 用甘特图控件VARCHART XGantt搞定项目管理
  10. jqprint 分页打印_jQuery打印Html页面自动分页
  11. 【学习笔记】InformationTheory——熵,条件熵,联合熵,互信息,交叉熵
  12. android八方向手势,Android开发中顺时针逆时针滑动手势的识别算法
  13. 服务器故障与主板维修,服务器主板故障
  14. 在Excel中单元格内画斜分割线,且线两边写上内容
  15. mysql capi函数详解_CAPI函数描述(G-N)
  16. 虚拟主机和服务器的区别
  17. php group 用法,thinkphp5 链式操作group分组用法
  18. 特步公布全新战略定位世界级中国跑鞋;电通集团计划过渡到新的全球集成领导架构 | 美通企业日报...
  19. 【新知实验室】——腾讯云音视频TRTC体验
  20. 微信weui之actionSheet应用

热门文章

  1. 借助实时数据推送快速制作在线对战五子棋小游戏丨实战
  2. Linux系统添加永久静态路由的方法
  3. 【读书笔记】计算机是怎样跑起来的
  4. 生成下拉框的几种方法总结——数据来源:枚举
  5. Swift 将日期转化为字符串,显示上午还是下午
  6. C++之类的静态成员变量和静态成员函数
  7. JavaWeb学习过程 之c3p0的使用
  8. 关于NPN和PNP传感器的应用区别(转载)
  9. Web应用中request获取各种获取path或URI,URL的方法
  10. 安卓学习日记:初识Android Studio · java环境配置和AS安装