def demo(fun):
def inner():
print("hello word")
return fun()
return inner
@demo
def decorator():
print("哈哈哈")
if __name__ == '__main__':
decorator()
一个函数在没有呗调用的时候是不会执行的,所以demo函数在代码运行的时候不会直接执行,直到@demo
的时候才会被调用,他等同于demo(decorator),把呗装饰的函数当作参数传入,执行的结果在返回decorator函数
多层装饰
def demo1(fun):
def wrapped():
return "<li>" + fun() + "</li>"
return wrapped
def demo2(fun):
def wrapped():
return "<b>" + fun() + "</b>"
return wrapped
@demo1
def test1():
return "hello world"
@demo2
def test2():
return "hello world"
@demo1
@demo2
def test3():
return "hello world"
print(test1())
print(test2())
print(test3())
----------------
<li>hello world</li>
<b>hello world</b>
<li><b>hello world</b></li>
装饰器的常用场景
引入日志
函数执行时间统计
执行函数前预备处理
执行函数后清理功能
权限校验
缓存
被装饰函数又参数:
def demo1(fun):
def wrapped(a,b):
print(a,b)
fun(a,b)
@demo1
def demo2(a,b):
print("%s + %s = %s", %(a, b, a+b))
demo2(1,4)
--------------------
2 4
2 + 4 = 6
被装饰的函数是不定长参数
def demo1(fun):
def wrapped(*args, **kwargs):
print(*args, **kwargs)
fun(*args, **kwargs)
return wrapped
@demo1
def demo2(a, b, c):
print("%s + %s = %s" % (a, b, a + b))
demo2(2,4, 3)
-------------------------------
2 4 3
2 + 4 = 6
装饰器可以在原有基础上再设置外部变量
def laowang(pre):
def demo1(fun):
def wrapped():
print(fun() + pre)
return wrapped
return demo1
@laowang("itcast")
def demo2():
return "哇哈哈"
demo2()
---------------------------------
哇哈哈itcast
由于饰的参数被当作参数传给了装饰器,而它return的却是wrapped,函数名称已经发生了改变,
可以用wraps来取消这些副作用,使用装饰器一帮都加上
@functools.wraps(func)
import functools
def note(func):
"note function"
@functools.wraps(func)
def wrapper():
"wrapper function"
print('note something')
return func()
return wrapper
@note
def test():
"test function"
print('I am test')