看一个正常的装饰器:
def deco(*arg):
print(1, arg)
def inner(func):
print(2, func)
print('inner')
return func
return inner
然后我们装饰一个函数:
@deco('arg')
def main():
return
打印结果如下:
1 ('arg',)
2 <function main at 0x0000017174880310>
inner
一点毛病没有,1
的打印位置就是事先处理区域,先执行了,再将 main()
当做 func
传入,执行 inner()
内的内容。
试想我们将函数传入:
def deco(*arg):
print(1, arg)
def inner(func):
print(2, func)
print('inner')
return func
return inner
def test():
return
@deco(test)
def main():
return
这段和正常装饰器无异,那么 arg
就应该是传入的 test()
函数,打印如下:
1 (<function test at 0x000001CC83B90160>,)
2 <function main at 0x000001CC83B90310>
inner
之后我们试想给 return 的 inner 传入参数,他会把 main()
也就是被装饰的函数传入装饰器参数的函数中:
def deco(*arg):
print(1, arg)
def inner(func):
print(2, func)
print('inner')
return func
return inner(arg[0])
def test(fun):
print('test:', fun)
return
@deco(test)
def main():
return
这里给 inner()
只传了 arg[0]
一个,也就是我们传入的 test()
函数,打印如下:
1 (<function test at 0x000001C5BEED00D0>,)
2 <function test at 0x000001C5BEED00D0>
inner
test: <function main at 0x000001C5BEED0160>
可以发现 inner(func)
的参数因为我们传入 test()
函数污染了,不再是 main()
函数了,main()
函数跑到了 test()
函数的参数里。
从而我们就实现了,被装饰函数传入装饰器参数中的函数内调用!
这里传入的 test()
不可以换为其他的变量,他必须是可 callable 的,另外, 能给 return inner 传参,不也能给 return func 传参吗,给 func 传参就是给 main()
传参,这个一目了然,不是迷惑行为。
def deco(*arg):
print(1, arg)
def inner(func):
print(2, func)
print('inner')
return func(arg[0])
return inner
def test(fun):
print('test:', fun)
return
@deco(test)
def main(param):
print('main: ', param)
return
打印结果:
1 (<function test at 0x0000019F19CE00D0>,)
2 <function main at 0x0000019F19CE01F0>
inner
main: <function test at 0x0000019F19CE00D0>
给 func 传参的话,没什么不可理解的,把装饰器上的参数给被装饰的函数调用而已,而且还执行了 main()
函数。
不在 inner()
内主动调用 main()
(被装饰函数)为前提。
那么,正向装饰中,我们可以把 test()
传给 return func() 中作为参数,从而把装饰器参数中的函数传给了被装饰函数作为参数 + 调用被装饰函数。
在反向装饰中,我们用 test()
污染了 inner()
,从而实现了将被装饰函数传给装饰器参数中的函数作为参数 + 调用装饰器参数中的函数。