一、装饰器函数
装饰器设计模式的作用:用装饰器写的代码优雅、在不更改函数的基础上为函数增加额外的功能
1、不带参数
def add_hold(fun):
def wrap():
return '<a>' + fun() + '</a>'
return wrap
@add_hold
def test():
return "hello"
if __name__ == '__main__':
print(test())
-----输出结果----------
<a>hello</a>
2、带参数
def log(filename: str):
print(filename)
def inner(fun):
def wrapper(*args, **kwargs):
return fun(*args, **kwargs)
return wrapper
return inner
@log(filename='xxxx.log')
def f(x, y):
return x + y
if __name__ == '__main__':
print(f(1, 2))
-----输出结果----------
xxxx.log
3
其实装饰器带参数就是在原来不带参数的外层又加了一层。
3、装饰器中的@
函数装饰器里的@可以大致理解为调用其后面紧接的对象的__call__()方法,所以一个对象能不能加(),取决于改对象有没有__call__属性
二、类装饰
1、不带参数
class A:
def __init__(self, fun):
self.fun = fun
# __call__当对一个对象加()进行调用时,此方法会自动执行
def __call__(self, *args, **kwargs):
pass
@A
def f(x, y):
pass
if __name__ == '__main__':
f(1, 2)
# a=A(f) 注意:类和函数,直接加括号是可以的
# a(1,2) 但是由类创建的对象,一般不能加括号的 TypeError: 'A' object is not callable
2、带参数
from functools import wraps
class PrintAfterExecutionDecoratorClass:
def __call__(self, func):
@wraps(func)
def wrapped_func(*args, **kwargs):
ret = func(*args, **kwargs)
print(ret)
return ret
return wrapped_func
@PrintAfterExecutionDecoratorClass()
def work_c(i):
return i+1
三、@wraps的作用
@wraps装饰器的作用,就是在调用函数的时候,使被装饰函数的__name__属性不被装饰器所影响
加@wraps(fun)装饰器
def add_hold(fun):
@wraps(fun)
def wrap():
return '<a>' + fun() + '</a>'
return wrap
@add_hold
def test():
print(test.__name__)
return "hello"
if __name__ == '__main__':
print(test())
-----输出结果----------
test
<a>hello</a>
不加@wraps(fun)装饰器
def add_hold(fun):
# @wraps(fun)
def wrap():
return '<a>' + fun() + '</a>'
return wrap
@add_hold
def test():
print(test.__name__)
return "hello"
if __name__ == '__main__':
print(test())
-----输出结果----------
wrap
<a>hello</a>
通过上述2个例子可以看出,当加了@wraps(fun)装饰器后,打印的__name__依然是原函数的,而不是装饰器内的函数名称。