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
http://bugs.python.org/issue1009444
This was back in Python 2.4. See this commit: python/cpython@ce220b0#diff-cb296cc5109f5640ff3f6d7198a6abeeL4135.