What order does Python execute decorators in? It seems like this changed sometime between when they were first introduced (2.4) and now (2.7).
Given the code:
@foo
@bar
@baz
def myfunc():
pass
Is the decorator calling order baz -> bar -> foo
, or is it foo -> bar -> baz
? It used to be from the bottom to the top (the decorator closest to your function def runs first), but now it seems to be run from top to bottom.
Or rather, is the code equivalent to foo(bar(baz(myfunc)))
(bottom to top) or baz(bar(foo(myfunc)))
(top to bottom)
Links that support one vs. the other:
- Bottom to top (inside-out) order:
- Multiple Decorators for python functions
- PEP 318 - See "order of application" (bottom to top)
- Python decorators finally demystified -
@bread, @ingredients def sandwich
=>bread(ingredients(sandwich))
- Top to bottom (code) order:
- How can I make a chain of function decorators in Python?
- A guide to Python decorators
@div_decorate, @p_decorate, @strong_decorate
=><div><p><strong>...</strong></p></div>
Test script:
#!/usr/bin/env python
from functools import wraps
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
print "login_required called!"
return f(*args, **kwargs)
return decorated_function
def ajax_request(f):
@wraps(f)
def decorated_function(*args, **kwargs):
print "ajax_request called!"
return f(*args, **kwargs)
return decorated_function
@login_required
@ajax_request
def test1():
print "Test 1, login above ajax"
@ajax_request
@login_required
def test2():
print "Test 2, ajax above login"
test1()
print "=" * 80
test2()
Output (Python 2.7.5):
** login_required called!
** ajax_request called!
Test 1, login above ajax
================================================================================
** ajax_request called!
** login_required called!
Test 2, ajax above login
Here is a code example that helps to remember
This outputs
I feel like the before and after of the onion skinning is what mostly confuses people.
But also, notice the definition of hello is only passed to the first in the onion skin. What is passed to the second is the wrapped hello output of the
@decorator('last')
. Don't confuse execution order with definition order.