python装饰器方法
前几天向几位新同事介绍项目,被问起了@login_required的实现,我说这是django框架提供的装饰器方法,验证用户是否登录,只要这样用就行了,因为自己不熟,并没有做过多解释。
今天查看django官网,忽然发现,装饰器用法并不是django框架提供的,而是python的一种语法,真心汗一个,自以为python用的很熟了,看来是井底之蛙!
恰逢周末,静下心来了解一下python的装饰器方法。
谈到代码里的装饰器,很自然的想到了设计模式中的装饰器模式,为了防止再次张冠李戴,特意翻了翻设计模式的书,确定python装饰器语法的功能就是类似于装饰器模式要实现的功能。
关于python装饰器语法,简单的说就是把要执行的方法foo用一段代码包装起来,在调用foo方法的前前后后增加一些逻辑,然后把这个新方法赋给foo。
也可以在包装的逻辑里写一个封装方法,传入参数,进行一些操作。注意一点,有多个装饰器方法包装foo时,应该是按照从下往上的顺序进行包装。
def before(pre=''): def dec(f): def wrapper(): print pre + " before function" f() return wrapper return dec def middle(f): def wrapper(): f() print "middle function" return wrapper def after(f): def wrapper(): f() print "after function" return wrapper def nextbefore(f): def wrapper(): print "nextbefore function" f() return wrapper @middle @after @nextbefore @before("hello") def test(): print "I'm tester" if __name__ == '__main__': test()
打印的结果:
>>> nextbefore function hello before function I'm tester after function middle function >>>
如果被装饰的函数带有参数,则利用装饰器函数内部的wrap函数传参
def mydecorate(func): def wrapper(param): print param func(param) return wrapper @mydecorate def foo1(param): print "Hello " + param
if __name__ == "__main__":
foo1("Andy")
返回结果:
>>>
Andy
Hello Andy
如果是带有参数装饰器,比如:
@decorate(arg)
def foo(param)
则相当于foo=decorate(arg)(foo), 即装饰器函数decorate(arg)返回结果为一个装饰器,这个装饰器再传入函数参数foo
def decorate1(para): def real_decorate(func): print para def wrapper(ff): func(ff) return wrapper return real_decorate @decorate1("hello") def foo(username): print "welcome " + username; if __name__ == "__main__": foo("Andy")
返回结果:
>>>
hello
welcome Andy
>>>
如果带参数的装饰器还有装饰器,则等同于 foo=decorate2(decorate1(arg)(foo)) or foo=decorate2(arg1,arg2)(decorate1(arg)(foo))