装饰器的用途:当写好一些函数,想对这些函数添加额外的附加功能(例如:登录验证,授权,日志等),而不改变原来函数的写法和调用,就需要用到装饰器。
装饰器特点:
- 代码重用
- 不改变已写函数的本身
- 不影响函数的返回结果
示例一
我有下面两个函数,很easy。我想对这两个添加一个功能,再执行之前添加个登录的功能。
def do():
print "do something"
def gan():
print "gan something"
如果不用装饰器,你可能会这么写
def do():
print "login"
print "do something"
def gan():
print "login"
print "gan something"
do()
gan()
执行结果:
login
do something
login
gan something
代码重用,太tmd的low了,是不是。于是你换了个招数
def begin():
print "login"
def do():
begin()
print "do something"
def gan():
begin()
print "gan something"
do()
gan()
你定义了一个新的函数,begin(),他可以完美的是现实了代码复用。但是还是对原来的函数进行了改动。我们已经做好的功能要尽可能少的改动,为了稳定。所以在这里装饰器应运而生。其实装饰器的道理很简单,就是像上面函数一样,函数套函数。
将上面功能改为装饰器实现
def begin(fun):
def inner():
print "login"
return fun()
return inner
@begin
def do():
print "do something"
@begin
def gan():
print "gan something"
记住个概念,函数即使变量。所以可以把一个函数的名称当成实参传递给另外一个函数。你print一个函数名时会打印出内存地址
上面装饰器就是最基本的写法,需要注意几点:
- “@begin”是python的语法糖,即为调用装饰器。此时do()相当于 do = begin(do)
- 定义装饰器时返回的值为 函数地址 “return inner”而不是“return inner()”。因为下面你调用的时候直接do(),而不是do
示例二,函数单个传参
def begin(fun):
def inner(args):
print "login"
return fun(args)
return inner
@begin
def do(name):
print "%s do something" %name
do("Reba")
结果:
login
Reba do something
将函数的参数传给inner函数,inner函数在传给fun函数
示例三,由于装饰器用来装饰很多函数,所以参数很有可能不固定,所以传递多个参数
def begin(fun):
def inner(*args,**kwargs):
print "login"
return fun(*args,**kwargs)
return inner
@begin
def do(name,age):
print "%s do something" %name
print "age:",age
do("Reba","22")
结果:
login
Reba do something
age: 22
示例四 ,在函数执行前和执行后都加入装饰器。用的不多,到时候再看也行
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'
Index("11111111","22222222")
结果:
before
index
after
装饰器的用处还是挺多的,希望对你有些帮助。