python装饰器其核心就是一个函数,类似于spring中的AOP。
通常来说,该函数接受被装饰的函数作为参数,执行某些操作后,返回该参数或者返回调用该参数的函数。
一般来说装饰器有下列几种用法:
1.在装饰时对被装饰的函数进行操作
def doc_decorate(func):
func.__doc__ = "return the sum of @param x and @param y"
return func
@doc_decorate
def foo(x, y):
return x + y
if __name__ == '__main__':
print foo.__doc__
结果
return the sum of @param x and @param y
这里装饰器对foo函数的_ doc_属性进行了修改
2.在函数执行时进行操作
验证参数类型
def decorate(func):
def inner(x, y):
if not isinstance(x, int) or not isinstance(y, int):
raise TypeError("only accept integers as param")
return func(x, y)
return inner
@decorate
def foo(x, y):
return x + y
if __name__ == '__main__':
foo('1', 2)
执行foo(‘1’,2)将抛出TypeError
另外,如过运行help(foo)将打印函数inner的帮助信息
Help on function inner in module _ main_:
inner(x, y)
这是因为装饰器作用后变量foo的引用不再是原来的foo函数而是装饰器内inner函数
这是由于装饰器实际上语法与下列相同
foo = decorate(foo)
这里用@functools.wraps来解决这个问题
import functools
def decorate(func):
@functools.wraps(func)
def inner(x, y):
if not isinstance(x, int) or not isinstance(y, int):
raise TypeError("only accept integers as param")
return func(x, y)
return inner
@decorate
def foo(x, y):
return x + y
if __name__ == '__main__':
help(foo)
结果
Help on function foo in module _ main_:
foo(x, y)
3.带参数的装饰器
import functools
def decorate_with_param(*args, **kwargs):
def decorate(func):
@functools.wraps(func)
def inner(x, y):
print args # 打印参数
if not isinstance(x, int) or not isinstance(y, int):
raise TypeError("only accept integers as param")
return func(x, y)
return inner
return decorate
@decorate_with_param('1', '2')
def foo(x, y):
return x + y
if __name__ == '__main__':
print foo(1, 2)
结果
(‘1’, ‘2’)
3
4.装饰类的装饰器
重写类的_ repr _方法
def decorate(func):
@functools.wraps(func)
def override_repr(*args, **kwargs):
func.__repr__ = lambda self: "this is the class named " + func.__name__ # 重写类的_ _repr_ _方法
return func(*args, **kwargs)
return override_repr
@decorate
class Funny:
def __init__(self):
pass
def __repr__(self):
return "class"
if __name__ == '__main__':
print Funny()
结果
this is the class named Funny
5.类型转换
def de(func):
class task(object):
def __call__(self, *args, **kwargs):
return func(*args, **kwargs)
return task()
@de
def fo(x, y):
return x+y
if __name__ == '__main__':
print fo(1, 2) # 此时fo变量的引用为task实例
结果
3