python装饰器的顺序

python装饰器的顺序是由下往上,但是如下程序的输出常令很多人困惑。为什么不是 1, 11, 2, 22, 3 这样的顺序?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def a(func):
print('1')
def aa():
print('11')
func()
return aa
def b(func):
print('2')
def bb():
print('22')
func()
return bb
@b
@a
def p():
print('3')
p()

输出:

1
2
22
11
3

首先要明白,多个装饰器:

1
2
3
4
5
@a
@b
@c
def f ():
pass

相当于 f = a(b(c(f)))

所以,最上面 p = b(a(p))
a(p): 打印 1,返回函数引用 aa,但aa本身并未被执行。
b(a(p)): 相当于 b(aa), 此时b打印 2,返回函数引用bb。
p(): 相当于执行函数bb(),此时打印 22,
接着执行bb()函数里面的func(),而这个func是函数b的入参,即aa,即实际执行aa(), 开始打印 11,
接着执行aa()里面的下一句,func(), 而此func是函数a的入参即函数p,即执行函数p(),打印 3.

加入更多埋点来观察:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def a(func):
print('1')
def aa():
print('11')
func()
print('111')
return aa
def b(func):
print('2')
def bb():
print('22')
func()
print('222')
return bb
@b
@a
def p():
print('3')
p()

输出:

1
2
22
11
3
111
222