2 things: decorators are applied when the function definition is executed, and the @expression
syntax takes an expression; it is evaluated when decorating.
The line @decorator_args(1)
calls the decorator_args()
function, passing in 1
as an argument. The result of that call is used as the decorator.
Decorators are really just syntactic sugar, this:
@decorator_args(1)
def foo_args(arg0):
print "foo_args"
is really executed as:
def foo_args(arg0):
print "foo_args"
foo_args = decorator_args(1)(foo_args)
Note that decorator_args(1)
is called. And it's return value is called again, to produce a decorated result.
When you look at decorator_args()
you see it returns a decorator:
def decorator_args(* args, **kargs):
def wrapper0(fn):
def wrapper1(*args, **kargs):
return fn(*args, **kargs)
return wrapper1
print "decorator_args"
return wrapper0
wrapper0
is the real decorator; it is returned when decorator_args()
is called. foo_args()
is passed to wrapper0()
(as the fn
argument), and the original function is replaced by wrapper1
.
It doesn't matter at all that foo_args
is never called; decorators are not applied each time when you call the function, they are only applied once. If you called foo_no_args()
more than once, the decorator_no_args
message will not be repeated.