要完全理解装饰器,需要先从闭包开始,下面的代码应该比较好理解:
def w1(func):
def inner():
print("----内部函数-----")
func()
return inner
def f1():
print("----f1----")
def f2():
print("----f2----")
innerFunc = w1(f1)
innerFunc()
上面其实就是一个闭包,执行后,将输出:
----内部函数-----
----f1----
如果修改一下,是否还可以理解呢:
def w1(func):
def inner():
print("----内部函数-----")
func()
return inner
def f1():
print("----f1----")
def f2():
print("----f2----")
f1 = w1(f1)
f1()
上面的代码输出是不会变的。需要说明的是执行完f1 = w1(f1)后,左边的f1是指向函数w1的内部函数inner()的。这里其实就是装饰器的雏形。稍微修改一下是装饰器了,如下:
def w1(func):
def inner():
print("----内部函数-----")
func()
return inner
# @w1 其实就是 f1 = w1(f1)
@w1
def f1():
print("----f1----")
def f2():
print("----f2----")
f1()
输出不变:
----内部函数-----
----f1----
总结:装饰器可以理解成一种特殊的闭包,将一个函数(f1)传入另个函数(w1)的内部函数(inner),并在内部函数中执行,在执行过程中内部函数可以对传入的函数进行一个功能扩展。需要说明的是,以上面的代码为例,程序运行到f1()之前,@w1是会先执行的,也就是说会先执行f1 = w1(f1)这句。
def makeBold(fn):
def wrapped():
print("----1----")
return "" + fn() + ""
return wrapped
def makeItalic(fn):
def wrapped():
print("----2----")
return "" + fn() + ""
return wrapped
@makeBold
@makeItalic
def test():
print("----3----")
return "hello world"
ret = test()
print(ret)
输出如下:
----1----
----2----
----3----
hello world
# 可以有参数,可以有返回值的装饰器
def func(functionName):
def func_in(*args, **kwargs):
ret = functionName(*args, **kwargs)
return ret
return func_in
@func
def test1():
print("----无参数,无返回值----")
@func
def test2():
print("----无参数,有返回值----")
return "返回值:test2"
@func
def test3(a):
print("----有参数,有返回值----")
return "返回值:{}".format(a)
test1()
print(test2())
print(test3(666))
输出:
----无参数,无返回值----
----无参数,有返回值----
返回值:test2
----有参数,有返回值----
返回值:666
def func_arg(arg):
def func(functionName):
def func_in():
if arg == "装饰器参数":
functionName()
else:
print(arg)
return func_in
return func
# 注意是先执行func_arg("装饰器参数")函数,然后返回func,再执行@func
@func_arg("装饰器参数")
def test1():
print("----传递装饰器的参数----")
@func_arg("不传值")
def test2():
pass
test1()
test2()
输出:
----传递装饰器的参数----
不传值