装饰器就是一个普通的函数,它一般用于将传入的函数或者类做一定的处理,返回新的函数或者类。
不带参数的函数装饰器
假如我们需要在每个函数的开始和结束处打印一条日志,我们就可以通过装饰器来实现
#定义一个装饰器
def add_log(f):
def deco(*args, **kwargs):
print "start of function %s" % f.func_name
re = f(*args, **kwargs)
print "end of function %s" % f.func_name
return re
return deco
#用装饰器装饰两个函数
@add_log
def add(x, y):
return x + y
@add_log
def dec(x, y):
return x - y
print add(1, 2)
print dec(1, 2)
输出:
> start of function add
> end of function add
> 3
> start of function dec
> end of function dec
> -1
其中的@add_log相当于add = add_log(add)和dec = add_log(dec)
这里有一个问题,打印add.func_name发现它等于deco,如果我们的程序对函数名有依赖的话,显然加了这个装饰器就会影响它的功能。
幸好python内置的functools模块可以将函数原来的属性全部复制到新函数上。
将原来的装饰器改为:
from functools import wraps
def add_log(f):
@wraps(f)
def deco(*args, **kwargs):
print "start of function %s" % f.func_name
re = f(*args, **kwargs)
print "end of function %s" % f.func_name
return re
return deco
这样装饰后的add的函数名就是add了
带参数的函数装饰器
假如我们需要在函数的开始和结尾处打印的日志里加上作者的信息,我们可能通过给装饰器加参数实现:
from functools import wraps
#定义一个装饰器
def add_log(author):
def first_deco(f):
@wraps(f)
def deco(*args, **kwargs):
print "start of function %s defined by %s" % (f.func_name,author)
re = f(*args, **kwargs)
print "end of function %s" % f.func_name
return re
return deco
return first_deco
#用装饰器装饰两个函数
@add_log('xb')
def add(x, y):
return x + y
@add_log("xb")
def dec(x, y):
return x - y
print add(1, 2)
print dec(1, 2)
print add.func_name
输出
start of function add defined by xb
end of function add
3
start of function dec defined by xb
end of function dec
-1
add
其中的@add_log相当于add = add_log(‘xb’)(add)和dec = add_log(‘xb’)(dec)
参数为类的情况类似这里就不再举例了