Python 装饰器这东西对初学者来说是个坑,很容易绕晕,笔者当时初学装饰器时花费了数天时间,看了不同讲师对这块内容的讲解,还是一知半解。 ?
?不过装饰器在开发中可是很好用的,有必要攻破,希望这篇文章能帮助学习者快速攻破难关。
初步理解
#?先来看一个简单函数
def?show():
????print?('Mr?tu')
show()
#?执行结果?:
Mr?tu
#?现在我们用装饰器扩展这个函数,在打印?"?Mr?tu?"?之前打印一行?"?hello?"??
def?decorate(fun1):
????def?wapper():
????????print('hello')
????????fun1()
????return?wapper
@decorate
def?show():
????print?('Mr?tu')
show()
#?执行结果?:
hello
Mr?tu
#?现在解释上面的代码。
#?1、首先?def?decorate(fun1)?定义一个装饰器函数,在此函数里又定义了一个wapper子函数,子函数可以继承父函数的参数。
#?2、?@'函数名'是Python的一种语法糖?@decorate?等于?decorate(show)?
#?还是晕,不明白???没关系,看下面代码:
def?decorate(fun1):
????def?wapper():
????????print('hello')
????????fun1()
????return?wapper
def?show():
????print?('Mr?tu')
f1?=?decorate(show)
f1()
#?执行结果?:
hello
Mr?tu
#?换成这种写法,执行效果是一样的,因为这就是?@decorate?的本质。
#?就是将被装饰器装饰的函数show作为参数传给装饰器函数。
#?总结执行过程:
#?1、show函数作为参数传给装饰器函数?decorate?,那么?fun1?=?show
#?2、这时执行到装饰器的子函数?wapper,子函数可以继承父函数的参数,所以可以调用?fun1?
#?3、然后wapper函数执行?print?打印一行?"hello"?,?再然后??调用fun1()?——?这里其实就是执行了show函数。??因为在装饰器一开始执行的时候就把show函数作为参数赋值给了fun1.
#?现在明白了吧,只要这里明白,下面的就很好理解了。
装饰带参数的函数
#?一个参数
def?decorate(fun1):
????def?wapper(arg1):
????????print('hello')
????????fun1(arg1)
????????print('nice?to?meet?you')
????return?wapper
@decorate
def?show(arg1):
????print?(arg1)
????
show('Mr?Alice')
#?执行结果:
hello
Mr?Alice
nice?to?meet?you
#?两个参数
def?decorate(fun1):
????def?wapper(arg1,arg2):
????????print('hello')
????????fun1(arg1,arg2)
????????print('nice?to?meet?you')
????return?wapper
@decorate
def?show(arg1,arg2):
????print?(arg1,arg2)
show('Mr?Alice','Mr?Tom')
#?执行结果:
hello
('Mr?Alice',?'Mr?Tom')
nice?to?meet?you
#?n个参数
def?decorate(fun1):
????def?wapper(*args,**kwargs):
????????print('hello')
????????fun1(*args,**kwargs)
????????print('nice?to?meet?you')
????return?wapper
@decorate
def?show(*args,**kwargs):
????print?(args[0])
????print?(args[1])
????print?(args[2])
show('Mr?Alice','Mr?Tim','Mr?tu')
#?执行结果:
hello
Mr?Alice
Mr?Tim
Mr?tu
nice?to?meet?you
一个函数被多个装饰器装饰
def?decorate01(fun1):
????def?wapper(*args,**kwargs):
????????print('hello?world')
????????print('I?am?decorate01')
????????fun1(*args,**kwargs)
????return?wapper
def?decorate02(fun1):
????def?wapper(*args,**kwargs):
????????print?('I?am?decorate02')
????????fun1(*args,**kwargs)
????????print('nice?to?meet?you')
????return?wapper
@decorate01
@decorate02
def?show(*args,**kwargs):
????print?(args[0])
????print?(args[1])
????print?(args[2])
show('Mr?Alice','Mr?Tim','Mr?tu')
#?执行结果:
hello?world
I?am?decorate01
I?am?decorate02
Mr?Alice
Mr?Tim
Mr?tu
nice?to?meet?you
#?观察print放置的位置不同,对应的输出结果不同。
def?decorate01(fun1):
????def?wapper(*args,**kwargs):
????????print('hello?world')
????????fun1(*args,**kwargs)
????????print('I?am?decorate01')??#?替换到了下面
????return?wapper
def?decorate02(fun1):
????def?wapper(*args,**kwargs):
????????print?('I?am?decorate02')
????????fun1(*args,**kwargs)
????????print('nice?to?meet?you')
????return?wapper
@decorate01
@decorate02
def?show(*args,**kwargs):
????print?(args[0])
????print?(args[1])
????print?(args[2])
show('Mr?Alice','Mr?Tim','Mr?tu')
#?执行结果:
hello?world
I?am?decorate02
Mr?Alice
Mr?Tim
Mr?tu
nice?to?meet?you
I?am?decorate01
装饰器功能扩展
#!/usr/local/python27/bin/python2.7
def?before(request,*args,**kwargs):
????print('before')
def?after(request,*args,**kwargs):
????print('after')
def?Filter(before_func,after_func):
????def?outer(fun1):
????????def?wapper(request,*args,**kwargs):
????????????before_result?=?before_func(request,*args,**kwargs)
????????????if(before_result?!=?None):
????????????????return?before_result;
????????????fun1_result?=?fun1(request,*args,**kwargs)
????????????if(fun1_result?!=?None):
????????????????return?fun1_result;
????????????after_result?=?after_func(request,*args,**kwargs)
????????????if(after_result?!=?None):
????????????????return?after_result;
????????return?wapper
????return?outer
@Filter(before,after)
def?show(request,*args,**kwargs):
????print?('Mr?tu')
????
show('1')
#?执行结果:
before
Mr?tu
after
函数若未定义返回值,执行成功返回值默认为 None ,这里的语句 if (before_result != None) 意思就是before函数执行失败时采取什么操作。