python之路(九)-函数装饰器
装饰器
某公司的基础业务平台如下:
def f1(): print('这是f1业务平台') def f2(): print('这是f2业务平台') def f3(): print('这是f3业务平台') def f4(): print('这是f4业务平台') def f5(): print('这是f5业务平台')
各业务部门是这样调用的:
#f1业务部门调用
f1()
#f2业务部门调用
f2()
#f1业务部门调用
f3()
#f4业务部门调用
f4()
#f5业务部门调用
f5()
随着公司的规模扩大,每个业务部门的研发越来越多,为了规范管理,此时需要各业务部门的研发在调用以上方法之前先登陆,认证成功后方可调用,有如下方案:
1. 让业务部门自己写登陆程序。
2. 基础平台写好认证程序,告诉业务部门研发在调用方法前先调用验证的方法。
3. 基础平台写好认证程序,并在每个方法内加入该验证程序。
4. 基础平台写好认证程序,然后再不改动原方法并且不改变业务部门调用原方法方式实现认证。
分析下以上方法,方法1肯定不合适,业务部门自己验证自己显然不符合要求。方法2每个业务部门都改变了调用方法,也不合适。方法3虽然没有改变业务部门调用方法但是在每个方法内加入同样的多行代码太复杂。方法4非常好,此时就需要用到函数装饰器具。
示例:
def wrapper(func): def inner(): print('验证成功') func() return inner @wrapper def f1(): print('这是f1业务平台') @wrapper def f2(): print('这是f2业务平台') @wrapper def f3(): print('这是f3业务平台') @wrapper def f4(): print('这是f4业务平台') @wrapper def f5(): print('这是f5业务平台') #f1业务部门调用 f1() #f2业务部门调用 f2() #f1业务部门调用 f3() #f4业务部门调用 f4() #f5业务部门调用 f5()
以上装饰器中,
@wrapper表示要对下面的函数进行装饰,此时要做的操作是:首先执行wrapper函数,然后将要装饰的函数名作为参数传给wrapper函数,wrapper函数的内容是定义了一个inner函数(注意只是定义了inner函数,并未执行),inner函数内先执行登陆功能函数,然后在执行被装饰的函数,所以wrapper函数相当于重新包装了一下被装饰的函数,比如f1函数,在包装f1函数的时候先执行了验证的方法,然后再执行f1函数。此时如果业务部门执行f1函数,那么他执行的是被包装后的函数及inner函数。此为装饰器。
问题:被装饰的函数如果有参数呢?
示例1:一个参数
def wrapper(func): def inner(args): print('login successfull!') func(args) return inner @wrapper def f1(args): print('your name is %s' %args) f1('Tomcat')
#输出结果:
login successfull!
your name is Tomcat
#我们说了 inner函数就是装饰器重新包装的被装饰的函数,所以inner函数的参数就是原函数f1的参数
示例2:两个参数
def wrapper(func): def inner(args1,args2): print('login successfull!') func(args1,args2) return inner @wrapper def f1(args1,args2): print('your name is %s and your age is %s' %(args1,args2)) f1('Tomcat','23') #输出结果: login successfull! your name is Tomcat and your age is 23
示例3:三个参数
def wrapper(func): def inner(*args,**kwargs): print('login successfull!') func(*args,**kwargs) return inner @wrapper def f1(args1,args2,args3): print('your name is %s and your age is %s,%s' %(args1,args2,args3)) f1('Tomcat','23','boy') #输出结果: login successfull! your name is Tomcat and your age is 23,boy
更叼的装饰器(装饰器具中带参数):
#!/usr/bin/env python #coding:utf-8 def Before(request,kargs): print 'before' def After(request,kargs): print 'after' def Filter(before_func,after_func): def outer(main_func): def wrapper(request,kargs): before_result = before_func(request,kargs) if(before_result != None): return before_result; main_result = main_func(request,kargs) if(main_result != None): return main_result; after_result = after_func(request,kargs) if(after_result != None): return after_result; return wrapper return outer @Filter(Before, After) def Index(request,kargs): print 'index'