引言:
这部分关于装饰器的内容需要前面闭包的知识作为基础。装饰器有点类似于我们java web里面经常讲到的面向切面编程(AOP),一切原理都是相通的。
一.什么是AOP
简单点来说,其实是为了更好的对程序进行控制,提高代码的可重用性。
在某段程序执行前面加上我们的控制代码。其实就是对原有函数进行了一层包装。(装饰器通俗点来说,就是对函数的二次封装)
下面我将通过一个案例来说明。
在我们开发java web网站时,我们需要对用户访问的网页进行验证工作,并记录下用户的网页浏览轨迹。我们的逻辑代码通常是:
1)验证用户是否登陆,并且是否有该权限
2)返回用户相应需要的网页资源
3)对用户进行记录
此时我们知道只有(2)才是我们的核心业务,(1),(3)是用于控制权限,分析等用途。如果我们需要对所有的网页都进行如上的操作,是否我们(1),(3)这部分公共的控制代码都需要放入所有的程序中。这样一来产生了很多垃圾代码,不利于程序的可重用性。二来,不利于以后的维护,如果(1),(3)中代码需要修改,那我们需要修改所有涉及到(1),(3)的代码。面向切面编程就是把公用的代码段抽取出来,在每个需要执行的程序中自动执行这段代码即可。不需要修改原有的程序。
#程序1:
validate() #validate the authority
process1() #process the user1 need
log() #log the user recorder
#程序2:
validate() #validate the authority
process1() #process the user1 need
log() #log the user recorder
#修改后程序:
def operate(process):
validate()
process()
log()
#如我们需要执行process1,()则我们执行operate(process1)即可。同理process2,这时我们操作的是一个经过包装的process函数。
二.闭包编程实现
def wrap(some_func):
def inner():
print("用户验证...")
some_func()
print("记录用户信息")
return inner
def process1():
print("process1")
def process2():
print("process2")
#对process1进行包装
process1=wrap(process1)
process1()
#对process2进行包装
process1=wrap(process2)
process2()
三.装饰器
装饰器其实就是提供闭包实现的语法糖@,装饰器就是对函数的二次封装。只要在需要包装的函数上面放入@wrapper即可。
def wrap(some_func):
def inner():
print("用户验证...")
some_func()
print("记录用户信息")
return inner
@wrap
def process1():
print("process1")
@wrap
def process2():
print("process2")
#对process1进行包装
process1()
#对process2进行包装
process2()
那么如何实现更通用的装饰器呢,真是场景中,我们需要通过参数传递来进行程序间的通信。python中提供了*args,**kwags这个不确定的参数形式,*args是不定长参数,**kwags是以字典形式存在的不定长参数。
我们通过实例来熟悉相关用户。
def wrap(some_func):
def inner(*args,**kwags):
print("before")
ret=some_func(*args,**kwags)
print("after")
return ret
return inner
@wrap #对加法进行包装
def add(a,b):
return a+b
@wrap #对减法进行包装
def sub(a,b,c):
return a-b-c
#对process1进行包装
result=process1(1,2)
print(result) #执行结果为3
#对process2进行包装
t=process2(5,2,1)
print(t) #执行结果为2