首页 > 开发 > Python > 正文

《python核心编程》中高级闭包和装饰器理解?

2017-09-06 19:16:49  来源:网友分享

1.《python核心编程》的这段程序怎么理解?对于这个函数,书上说两个wraaped是闭包,但是不知道谁是自由变量。

2.代码:

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

解决方案

关于闭包:
当一个内嵌函数引用外部作用域的变量,我们就会得到一个闭包。创建一个闭包必须同时满足以下几点:
1、必须要有一个内嵌函数。题目中外部函数是pre_logged,post_logged,对应的内嵌函数为wraper,wrapped。
2、内嵌函数中必须要引用外部函数的变量。题目中是引用来外部的args, *kwargs参数。
3、外部函数返回值必须是内嵌函数。题目中是用return wraper, return wrapped加以返回。

关于装饰器:
简单的说装饰器就是修改其他函数功能的函数。题中logged就是一个装饰器,他用来装饰你定义的hello函数。

@logged("post")def hello(name):    print "Hello, ", namehello('World!')

装饰器参数你传入了“post”,根据:return {"pre": pre_logged, "post": post_logged}[when]
调用了post_logged函数,post_logged的功能是打印花费的时间(time()-now)

关于装饰器的详细解释,可以参见《Python进阶》:
装饰器详解

这整本书都翻译的不错,推荐楼主看看。