5

I am trying to wrap my head around python's decorator. But there is something I don't understand. This is my code, my question is related to func_decorate2 (decorator with parameter).

def func_decorate(f):
  def wrapper():
    print('wrapped');
    f() 
  return wrapper

@func_decorate
def myfunc1():
  print('func1')

def func_decorate2(tag_name):
  def _(f):
    print('underscore')
    return f
  return _

@func_decorate2('p')
def myfunc2():
  print('func2')

print('call func1')
myfunc1()
print('call func2')
myfunc2()

Will output :

underscore
call func1
wrapped
func1
call func2
func2

Why do I have underscore first in this example ?

Thanks

jobou
  • 1,823
  • 2
  • 18
  • 28

2 Answers2

4

Because func_decorate2('p') executes immediately and returns a decorator that is then itself immediately executed when the interpreter uses it to decorate myfunc2.

The trick to realize is the part following the @ is just an expression. It doesn't have to be a function itself – it just needs to evaluate to one and the evaluation happens immediately on definition.

David K. Hess
  • 16,632
  • 2
  • 49
  • 73
  • 1
    Thx for your answer. I posted my question too soon. There is another one with the same problem : http://stackoverflow.com/questions/19102930/python-decorator-self-firing – jobou Sep 04 '15 at 13:07
0

Because func_decorate2 was wrong. If you want to use arguments in your decorator, you have to add one more def level

def func_decorate2(tag_name):
  def _(f):
    def _fun():
        print('underscore')
        return f
    return _fun
  return _
Anarchy
  • 46
  • 3
  • That's what I had a hard time understanding. I didnot see that the decorated was interpreted as `func_decorate2('p')(myfunc2)` – jobou Sep 04 '15 at 13:10