这周学到了python的装饰器,以前没有接触过,问了一个搞php开发的同事什么是装饰器,他说就好像构造函数一样,可惜我已经把构造函数忘得光光了,想不起来是啥了。现在就找资料了解了解。毕竟装饰器是一个不用也能实现程序的功能,但是用了装饰器以后会显得你的技术特NB,但是不太好理解
学装饰器之前,需要先了解一下函数,前面的笔记里,有写过函数相关的笔记,可以先去参考一下前面的文章,这里只简单说一下。
在python中,函数由 def 关键字,函数名,可选的参数列表和函数体 来组成,通过return语句来返回值,如果没有return语句的时候,函数自动返回一个None值,
装饰器其实就是把一个函数当做参数,然后返回一个替代版的函数,
def wrapper(a_fun): def fun(): print "a fun" tmp = a_fun() return tmp +1 return fun def w_test(): return 1 var1 = wrapper(w_test) print var1() #1 print w_test()
输出:
a fun # var1() 输出
2 # var1() 输出
1 # w_test() 输出
上面是一个装饰器的例子,我们定义了一个函数 wrapper() ,参数为一个名叫a_fun的函数,在函数内部定义了一个嵌套的函数 fun() 。fun() 会输出一串字符串,然后调用 a_fun(), tmp 可以得到a_fun()的返回值, wrapper每次调用 fun() 的时候值可能会不一样(如果使用的是其他函数),但是不管a_fun()的返回值 是什么,外面都会调用它,最后 fun() 的返回值为 a_fun()+1 。 在位置 #1处,我们调用存储在变量var1 里面的函数,可以得到打印出的字符串和返回值 2,而不是函数 w_test() 的返回值
我们可以认为 var1 是函数 w_test() 的一个装饰版本,或者说一个改造版本,而且并没有对原来的函数w_test() 进行任何改变。 写一个装饰器的话,外面可以用装饰版本 完全替换掉原来的函数w_test(),这样就可以得到一个 改造版 的函数w_test() , 在使用过程中 ,还不需要学习新的语法,只要简单的给变量复制就可以达到效果
w_test = wrapper(w_test) w_test 输出: <function fun at 0x7f5edf6c5668>
执行上面的代码后,外面再怎么调用都不会牵扯原来的函数w_test(),调用的会是改造版本的w_test()
再来一个具体的例子.
wrapper(func): result(): func() result foo(): foo = wrapper(foo) ### 这里 foo()
使用 @ 标识符 将装饰器应用到函数
python2.4 支持使用标识符讲装饰器应用到函数上,只需要在函数的定义钱叫上@和装饰器的名称,
上面的例子中,外面使用的方法是
foo = wrapper(foo)
这种方法可以在任何时候对任意的方法进行包装,但是代码写的多,累啊。我们可以使用简单的方法,使用@装饰,将上面的例子修改后:
wrapper(func): result(): func() result @foo(): foo()
需要记住的是, 使用 foo = wrapper(foo) 和在函数前加 @wrapper 这两种方法是一样的,python只是增加了一些语法糖 ,让装饰的行为更加直接明确和优雅,说白了 就是让你更容易看代码。
关于传递参数
上面我们已经完成了一个装饰器,但是这个装饰器只能应用在一类具体的方法上。如果我们想要实现一个能够应用在任何方法的装饰器上要怎么做呢?
其实可以猜出来一部分 使用*args 和 **kwargs。
例:
first(*args): args first() first(,,) lst = [,,,] first(*lst)
上面定义了函数 first ,将任何传递进来的参数打印, * 表示 调用的方法的时候,额外的参数可以从一个可迭代的列表中获得,或者是 定义方法的时候 表示这个参数可以接收任意数量的位置参数
** 比* 稍微复杂一点点, 使用**的时候,表示与其对应的是一个代表着键值对的参数字典。
例:
sec(**kwargs): kwargs dic = {:,:} sec() sec(=,=) sec(**dic)
让我们来写一个功能更强大的装饰器
war(func): in_war(*args,**kwargs): %(args,kwargs) in_war @foo_1(x,y=): x+y @foo_2(): foo_1(,) foo_1() foo_2()
http://timesnotes.blog.51cto.com/1079212/1715330
http://www.timesnotes.com/?p=111
本文出自 “Will的笔记” 博客,请务必保留此出处http://timesnotes.blog.51cto.com/1079212/1715330
原文地址:http://timesnotes.blog.51cto.com/1079212/1715330