# 探究多个装饰器执行顺序

## 疑问

``````def decorator_a(func):
print 'Get in decorator_a'
def inner_a(*args, **kwargs):
print 'Get in inner_a'
return func(*args, **kwargs)
return inner_a

def decorator_b(func):
print 'Get in decorator_b'
def inner_b(*args, **kwargs):
print 'Get in inner_b'
return func(*args, **kwargs)
return inner_b

@decorator_b
@decorator_a
def f(x):
print 'Get in f'
return x * 2

f(1)
``````

``````Get in decorator_a
Get in decorator_b
Get in inner_b
Get in inner_a
Get in f
``````

## 装饰器函数在被装饰函数定义好后立即执行

``````def decorator_a(func):
print 'Get in decorator_a'
def inner_a(*args, **kwargs):
print 'Get in inner_a'
return func(*args, **kwargs)
return inner_a

@decorator_a
def f(x):
print 'Get in f'
return x * 2
``````

``````@decorator_a
def f(x):
print 'Get in f'
return x * 2

# 相当于
def f(x):
print 'Get in f'
return x * 2

f = decorator_a(f)
``````

## 疑问的解释

``````@decorator_b
@decorator_a
def f(x):
print 'Get in f'
return x * 2
``````

``````➜  test git:(master) ✗ python
Python 2.7.11 (default, Jan 22 2016, 08:29:18)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
>>> import test13
Get in decorator_a
Get in decorator_b
>>> test13.f(1)
Get in inner_b
Get in inner_a
Get in f
2
>>> test13.f(2)
Get in inner_b
Get in inner_a
Get in f
4
>>>
``````

``````@login_required
@permision_allowed
def f()
# Do something
return
``````

# 参考资料

• 我的大脑和好奇心

#### 你可能感兴趣的

7 条评论
DZL1943 · 2017年02月19日

+2 回复

ipigzhu · 2018年07月17日

@登录没有判断
@权限判断
def fun():pass

jammywwh · 2018年08月03日

def decorator_b(func):

``````print ('Get in decorator_b') # 2
def inner_b(*args, **kwargs):
print ('Get in inner_b') # 3
return func(*args, **kwargs)
return inner_b
``````

def decorator_a(func):

``````print ('Get in decorator_a') # 1
def inner_a(*args, **kwargs):
print ('Get in inner_a') # 4
return func(*args, **kwargs)
return inner_a
``````

@decorator_b
@decorator_a
def f(x):

``````print ('Get in f')           # 5
return x * 2
``````

f # 分步骤来，这里很重要。这里会先后打印出Get in decorator_a 和Get in decorator_b

1、输入函数名f，意味着将函数f作为参数，传入装饰器a和b。 1.5、但是并未调用函数f(x)，也就是f(x)函数并不会执行，因为没有传入参数。重点也就在这，函数和函数调用是不一样的。 2、f首先传入装饰器a，也就是装饰器a函数获得参数被调用，那么就执行打印，并同时返回函数inner_a。 2.5、当然，此时函数inner_a也没有被调用。因为同样没有参数传入。 3、inner_a传入装饰器b，也就是装饰器b函数获得参数被调用，那么也执行打印，并同时返回函数inner_b。 4、现在就是返回函数inner_b>inner_a>f

f(1) # 然后输入这段代码，会先后打印出Get in inner_b和Get in inner_a，以及Get in f

5、此时函数f获得参数1，即函数被调用，由于上面步骤4中最后返回函数是inner_b，那么最先调用最外层的函数，print先行，也就是先打印Get in inner_b，再返回inner_a函数； 6、进而调用inner_a函数，print先行，也就是先打印Get in inner_a，再返回f(1)函数； 7、最后调用f(1)函数，print先行，也就是先打印Get in f，再返回2。 8、这样顺序就理顺了，哈哈，我这么理解的。

youyiqin · 2018年09月17日

• f(1)执行,装饰器decorator_b启动
• print 'Get in decorator_a' 打印,并且return一个函数inner_a
• 接着,这个函数inner_a被decorator_b装饰掉,于是
• print 'Get in decorator_b' 打印,再次return一个函数inner_b
• 因此,绕回来理解整个流程,f(1)调用了inner_b,打印了Get in inner_b
• 再执行了函数inner_a,打印了Get in inner_a
• 再执行了f函数,打印了Get in f

0

youyiqin · 2018年09月17日
learn者 · 2018年12月02日