转自:http://www.cnblogs.com/ma6174/archive/2013/04/15/3022548.html


python中的闭包

什么是闭包?

简单说,闭包就是根据不同的配置信息得到不同的结果

再来看看专业的解释:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

python实例

看概念总是让人摸不着头脑,看几个python小例子就会了

例1

def make_adder(addend):
def adder(augend):
return augend + addend
return adder p = make_adder(23)
q = make_adder(44) print p(100)
print q(100)
运行结果:
123
144
分析一下:

我们发现,make_adder是一个函数,包括一个参数addend,比较特殊的地方是这个函数里面又定义了一个新函数,这个新函数里面的一个变量正好是外部make_adder的参数.也就是说,外部传递过来的addend参数已经和adder函数绑定到一起了,形成了一个新函数,我们可以把addend看做新函数的一个配置信息,配置信息不同,函数的功能就不一样了,也就是能得到定制之后的函数.

再看看运行结果,我们发现,虽然p和q都是make_adder生成的,但是因为配置参数不同,后面再执行相同参数的函数后得到了不同的结果.这就是闭包.

例2

def hellocounter (name):
count=[0]
def counter():
count[0]+=1
print 'Hello,',name,',',str(count[0])+' access!'
return counter hello = hellocounter('ma6174')
hello()
hello()
hello()
执行结果
Hello, ysisl , 1 access!
Hello, ysisl , 2 access!
Hello, ysisl , 3 access!
分析一下

这个程序比较有趣,我们可以把这个程序看做统计一个函数调用次数的函数.count[0]可以看做一个计数器,没执行一次hello函数,count[0]的值就加1。也许你会有疑问:为什么不直接写count而用一个列表?这是python2的一个bug,如果不用列表的话,会报这样一个错误:

UnboundLocalError: local variable 'count' referenced before assignment.

什么意思?就是说conut这个变量你没有定义就直接引用了,我不知道这是个什么东西,程序就崩溃了.于是,再python3里面,引入了一个关键字:nonlocal,这个关键字是干什么的?就是告诉python程序,我的这个count变量是再外部定义的,你去外面找吧.然后python就去外层函数找,然后就找到了count=0这个定义和赋值,程序就能正常执行了.

python3 代码

def hellocounter (name):
count=0
def counter():
nonlocal count
count+=1
print 'Hello,',name,',',str(count[0])+' access!'
return counter hello = hellocounter('ma6174')
hello()
hello()
hello()

关于这个问题的研究您可以参考http://linluxiang.iteye.com/blog/789946

例3

def makebold(fn):
def wrapped():
return "<b>" + fn() + "</b>"
return wrapped def makeitalic(fn):
def wrapped():
return "<i>" + fn() + "</i>"
return wrapped @makebold
@makeitalic
def hello():
return "hello world" print hello()
执行结果
<b><i>hello world</i></b>
简单分析

怎么样?这个程序熟悉吗?这不是传说的的装饰器吗?对,这就是装饰器,其实,装饰器就是一种闭包,我们再回想一下装饰器的概念:对函数(参数,返回值等)进行加工处理,生成一个功能增强版的一个函数。再看看闭包的概念,这个增强版的函数不就是我们配置之后的函数吗?区别在于,装饰器的参数是一个函数或类,专门对类或函数进行加工处理。

python里面的好多高级功能,比如装饰器,生成器,列表推到,闭包,匿名函数等,开发中用一下,可能会达到事半功倍的效果!

【转】python中的闭包的更多相关文章

  1. 说说Python中的闭包 - Closure

    转载自https://segmentfault.com/a/1190000007321972 Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西 ...

  2. 说说Python中的闭包

    Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西. 闭包的概念 我们尝试从概念上去理解一下闭包. 在一些语言中,在函数中可以(嵌套)定义另一个 ...

  3. Python中的闭包 - Closure

    Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需要去了解这么一个东西. 闭包的概念 我们尝试从概念上去理解一下闭包. 在一些语言中,在函数中可以(嵌套)定义另一个 ...

  4. 21.python中的闭包和装饰器

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python ...

  5. 轻松理解python中的闭包和装饰器 (下)

    在 上篇 我们讲了python将函数做为返回值和闭包的概念,下面我们继续讲解函数做参数和装饰器,这个功能相当方便实用,可以极大地简化代码,就让我们go on吧! 能接受函数做参数的函数我们称之为高阶函 ...

  6. 轻松理解python中的闭包和装饰器(上)

    继面向对象编程之后函数式编程逐渐火起来了,在python中也同样支持函数式编程,我们平时使用的map, reduce, filter等都是函数式编程的例子.在函数式编程中,函数也作为一个变量存在,对应 ...

  7. Python 中的闭包

    通常来说,函数中的局部变量在函数调用结束的时候不能再被引用,所分配的空间也会被回收. 但是通过闭包这种技术,函数调用结束了,它的局部变量的值还可以保存在闭包里. 试举一例: def make_adde ...

  8. 聊聊Python中的闭包和装饰器

    1. 闭包 首先我们明确一下函数的引用,如下所示: def test1(): print("--- in test1 func----") # 调用函数 test1() # 引用函 ...

  9. python中的闭包与装饰器

    #原创,转载请留言联系 装饰器的本质就是闭包,所以想知道装饰器是什么,首先要理解一下什么是闭包. 闭包 1. 外部函数返回内部函数的引用.2. 内部函数使用外部函数的变量或者参数. def outer ...

随机推荐

  1. Ant默认配置文件不是build.xml该如何编写命令进行编译打包

    Ant的构件文件是基于XML编写的,默认名称为build.xml. ant命令默认寻找build.xml文件.若文件名为hello.xml时,读者还需要对命令做少许改变, 改为:ant –f hell ...

  2. vb.net 带有一个参数的线程

    For Each _row As DataGridViewRow In datagridview.Rows 'searchRecords_refreshRow(_row) ' 上面以前,直接运行函数, ...

  3. python-15-常用文件操作与注册登录练习

    前言 1.常用的文件操作无非就是读或写,但python中没有提供文件修改的功能,是无法实现,但我们可以新增-删除源文件-更改新增文件为源文件名称. 2.使用文件的存储与读取方式来简单完成注册.登录功能 ...

  4. 【Linux命令】安装命令(yum,rpm)

    安装软件有三种方式,第一种是源码安装(源码安装需要手动安装软件,安装的目录,还需要进行编译之后才能安装),步骤比较繁琐.第二种是RPM安装,rpm安装有点像windows系统的面板,会建立统一的数据库 ...

  5. WPF TextBox绑定Int类型的属性

    TextBox双向绑定int属性,清空输入框时Setter方法未触发. 我的解决方案: 1.属性置为int?: 2.xmlns:sys="clr-namespace:System;assem ...

  6. python验证码识别(2)极验滑动验证码识别

    目录 一:极验滑动验证码简介 二:极验滑动验证码识别思路 三:极验验证码识别 一:极验滑动验证码简介   近些年来出现了一些新型验证码,不想旧的验证码对人类不友好,但是这种验证码对于代码来说识别难度上 ...

  7. JS基本语法---while循环---练习

    JS基本语法---while循环---练习 练习1: 求6的阶乘 var ji = 1;//存储最终的阶乘的结果 var i = 1;//开始的数字 while (i <= 6) { ji *= ...

  8. 跳转常规 -- 为什么不要使用404、500等http状态码作为业务代码响应

    不要使用HTTP状态码作为业务代码响应 HTTP状态码 是指浏览器访问网址,成功或异常时浏览器或服务器告知用户的代码数字,它指的是网络或服务器的状态,有着不同的含义. 参加MDN.Java Api,常 ...

  9. Java --Lamda表达式

    Lamda:属于函数式编程的概念: interface IMessage { public void print() ; } public class TestDemo { public static ...

  10. ECharts grid组件离容器的距离

    ECharts grid组件离容器的距离 由 Carrie 创建, 最后一次修改 2017-09-04 grid.left   |   string, number [ default: '10%' ...