百度搜了一下闭包的概念:简而言之,闭包的作用就是在外部函数执行完并返回后,闭包使得收机制不会收回函数所占用的资源,因为内部函数的执行需要依赖外函数中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。
我自己的理解,就是给自己看的,也希望大神指点:闭包在外函数返回的内涵数,内函数用到了外函数的参数,并没有在整个函数外部声明一个参数用来存执行这个方法时希望存下来的值,仅仅在声明外函数得到内涵数的句柄时将参数的值持久,外函数和内函数相互引用,而又不受外界打扰。像下面的第一段代码,在count1不被回收的时候,5的这个值是一直被count1所引用的,在count1不被垃圾回收机制回收之前一直有效,外界却改变不了这个值,如果在生命一个count2,那又是count2自己的领域,和count1完全没关系。

在看书中的闭包的问题的时候,发现给了这样一段代码:

def counter(start_at=0):
count = [start_at]
def incr():
print count
count[0] += 1
return count[0]
return incr
count1 = counter(5)
count1()
结果:6

结果和预想的一样。但是发现了一个问题,count = [start_at]这个地方是用一个数组来封装的,为什么要弄成这样,于是自己修改了一下,数组去掉

def counter(start_at=0):
count = start_at
def incr():
print count
count += 1
return count
return incr
count1 = counter(5)
print count1()

(关于下面问题的研究,参考     http://linluxiang.iteye.com/blog/789946   )
运行报错:UnboundLocalError: local variable 'count' referenced before assignment
原因编译器看到a=a+1,检查右边发现了一个a的变量。编译器根据自己的规则(如果一个名字出现在参数声明,赋值语句(左边),函数声明,类声明,import语句,for语句和except语句中,这就是一个局部变量。)。编译器从头到尾看一遍,在a=a+1右边找到了a,决定他就是一个本地变量。编译器顺利赋值,但是在虚拟机运行的时候,虚拟机在计算a=a+1的时候并没有找到a的声明,于是报错。为什么数组正常,因为数组中的仅仅是一个引用。python的名字查找顺序:先local,再闭包,在global。

在记录一下闭包和装饰器的使用:

方法的参数也可以是方法:
deco方法中将原方法返回去,但是这么弄发现只有第一次(deco(func))的时候才调了装饰方法。

def deco(func):
print 'before func'
func()
print 'after func'
return func
def func():
print 'hello, bad_boy'
myfunc = deco(func)
myfunc()
myfunc()
结果:

  before func
  hello, bad_boy
  after func
  hello, bad_boy
  hello, bad_boy

怎么每次都调用新方法稍后在说,先看看怎么用装饰器来完成上面的功能。

def deco(func):
print 'before func'
func()
print 'after func'
return func
@deco
def func2():
print 'hello, bad_boy, hahaha'
func2()
func2()
结果
before func
hello, bad_boy, hahaha
after func
hello, bad_boy, hahaha
hello, bad_boy, hahaha

这里在声明func2的时候,就走了一遍deco方法,以后的每次调用都是deco中return 回来的那个方法,也就是func2。

然后解决上面留下的问题:

def deco1(func):
def inner_deco():
print 'before func'
result = func()
print 'after func'
return result
return inner_deco
@deco1
def func3():
print 'hello, bad_boy, hahaha'
func3()
func3()
结果:
before func
hello, bad_boy, hahaha
after func
before func
hello, bad_boy, hahaha
after func

每次调用都是调用的新的方法,最主要的是,在声明方法func3的时候,也就仅仅是一个声明,并没有执行,这是因为在deco1方法中,没有传进方法的执行语句,执行语句func()在inner_deco内部,而deco1方法仅仅返回的是inner_deco句柄。这段代码其实就是相当于func = deco1(func3)。
给方法中加上参数:

def deco2(func):
def inner_deco(x , y):
print 'before func'
result = func(x , y)
print 'after func'
return result
return inner_deco @deco2
def func4(x , y):
print 'x is ', x
print 'y is ', y
return x + y
print func4(1, 2)
结果:
before func
x is 1
y is 2
after func
3

如果在写inner_deco的时候,并不知道外面会传什么参数,那就用*args, **kwargs,下面会用到。
装饰器上也带有参数,借用《Python核心编程》中的例子

from time import time

def logged(when):
def log(f, *args, **kargs):
print '''Called:
function: %s
args: %r
kargs: %r''' % (f, args, kargs) def pre_logged(f):
def wrapper(*args, **kargs):
log(f, *args, **kargs)
return f(*args, **kargs)
return wrapper def post_logged(f):
def wrapper(*args, **kargs):
now = time()
try:
log(f, *args, **kargs)
return f(*args, **kargs)
finally:
print "time delta: %s" % (time() - now)
return wrapper
try:
return {"pre": pre_logged, "post": post_logged}[when]
except KeyError, e:
raise ValueError(e), 'must be "pre" or "post"' @logged("post")
def hello(name):
print "Hello,", name hello("World!")

如果想要在装饰器中也添加参数,也就得在包一层函数。理解一下,首先,到这里已经明白了,其实装饰器就是另外一个方法,方法中有参数,肯定得需要接受,在第一层函数中,是一定要接受装饰器参数的。装饰器的主要作用就是用来修饰一个方法,给这个方法添加一些额外的功能。一定会有一层函数来把要修饰的方法传进去,第二层函数就是来传递方法。方法传进来了还要有一层来执行这个方法。如果不用装饰器的方法(@logged("post")删掉),就是func = logged('post')(hello)      func('World!')这两句和利用装饰器的hello("World!")是等价的。

 

Python核心编程-闭包的更多相关文章

  1. Python核心编程的四大神兽:迭代器、生成器、闭包以及装饰器

      生成器 生成器是生成一个值的特殊函数,它具有这样的特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程 ...

  2. python核心编程第二版笔记

    python核心编程第二版笔记由网友提供:open168 python核心编程--笔记(很详细,建议收藏) 解释器options:1.1 –d   提供调试输出1.2 –O   生成优化的字节码(生成 ...

  3. python核心编程--笔记

    python核心编程--笔记 的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找pyt ...

  4. Python核心编程第二版(中文).pdf 目录整理

    python核心编程目录 Chapter1:欢迎来到python世界!-页码:7 1.1什么是python 1.2起源  :罗萨姆1989底创建python 1.3特点 1.3.1高级 1.3.2面向 ...

  5. python核心编程--笔记(不定时跟新)(转)

    的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找python路径 1.4 –v   ...

  6. python核心编程笔记(转)

    解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找python路径 1.4 –v   冗 ...

  7. Python核心编程(第二版)PDF

    Python核心编程(第二版) 目录 第1部分 Python核心第1章 欢迎来到Python世界1.1 什么是Python1.2 起源1.3 特点1.3.1 高级1.3.2 面向对象1.3.3 可升级 ...

  8. 拒绝从入门到放弃_《Python 核心编程 (第二版)》必读目录

    目录 目录 关于这本书 必看知识点 最后 关于这本书 <Python 核心编程 (第二版)>是一本 Python 编程的入门书,分为 Python 核心(其实并不核心,应该叫基础) 和 高 ...

  9. Python核心编程(第3版)PDF高清晰完整中文版|网盘链接附提取码下载|

    一.书籍简介<Python核心编程(第3版)>是经典畅销图书<Python核心编程(第二版)>的全新升级版本.<Python核心编程(第3版)>总共分为3部分.第1 ...

随机推荐

  1. Poj(2135),MCMF,模板

    题目链接:http://poj.org/problem?id=2135 Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  2. SQL锁行 解决多台服务器发送统一请求并发问题

    锁行信息SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 存储过程:SET Transaction Isolation Level Read语法的四种情 ...

  3. Multi-Perspective Sentence Similarity Modeling论文demo实现

    由于下载glove时,下载脚本并未自己执行txt文件转.th文件,在执行th trainSIC.lua时报错 需要根据fetch_and_preprocess.sh中的代码利用scripts中的con ...

  4. flume ng系列之——flume安装

    flume版本:1.5.0 1.下载安装包: http://www.apache.org/dyn/closer.cgi/flume/1.5.0/apache-flume-1.5.0-bin.tar.g ...

  5. 编译android源码官方教程(2)建立编译环境「linux & mac osx」

    https://source.android.com/source/initializing.html Establishing a Build Environment IN THIS DOCUMEN ...

  6. Linux有问必答:如何在Linux中修改环境变量PATH

    提问: 当我试着运行一个程序时,它提示“command not found”. 但这个程序就在/usr/local/bin下.我该如何添加/usr/local/bin到我的PATH变量下,这样我就可以 ...

  7. Create Stacked Canvas to Scroll Horizontal Tabular Data Blocks In Oracle Forms

    In this tutorial you will learn to create horizontal scrollable tabular or detail data block by usin ...

  8. sequenza细胞纯度计算

    安装sequenza bam文件要放在前面,否侧会-f命令可能识别错误 samtools mpileup a.bam -f hg19.fasta -Q 20 |gzip > normal.pil ...

  9. 《NoSQL精粹》思维导图读书笔记

    <NoSQL精粹>思维导图读书笔记 各主题笔记 这本书短小精悍,虽不能解答所有NoSQL疑问,但在读书过程中会抛给你不少未曾想过的问题,给人以更深入的思考: 这里对每一个主题分别做了笔记: ...

  10. 访问Google搜索,Google学术镜像搜索

    Google学术镜像搜索:http://dir.scmor.com/google/ 不用FQ也能访问谷歌搜索网站,让我们一起Google 不用FQ也能访问谷歌搜索网站,让我们一起Google(摘自:h ...