How to use two decorators in Python?

3

How can I do to use two decorators in python, as in the example below:

@makebold
@makeitalic
def say():
   return "Hello"

that returns:

<b><i>Hello</i></b>

I'm not trying to make HTML so in an actual application, I'm just trying to understand how decorators and groups of decorators work in Python.

    
asked by anonymous 21.08.2014 / 17:47

2 answers

2

Just define the functions:

def makebold(fn):
    def pacote():
        return "<b>" + fn() + "</b>"
    return pacote

def makeitalic(fn):
    def pacote():
        return "<i>" + fn() + "</i>"
    return pacote

@makebold
@makeitalic
def hello():
    return "Olá Mundo"

print hello() ## retorno <b><i>Olá Mundo</i></b>

See this example on codepad .

Note that wrapping wrapping is essential in these delimiters, the problem is that people generally believe that the delimiters do compound functions. What does not happen without this kind of packaging.

    
21.08.2014 / 17:57
1

Definition:

Decorators are functions returning another function using the syntax of @wrapper or packaging.

As described in official documentation decorators are nothing more than syntactic sugar.

For example the two definitions below are equivalent:

def f(...):
    ...
f = metodoestatico(f)

@metodoestatico
def f(...):
    ...

Use

In addition to the example given in the question and answer. It is possible to use decorators for other purposes and even to make a debug more efficient:

 def debugger(func):
    def f_interna(*args, **kwargs): #1
        print "Os argumentos foram: %s, %s" % (args, kwargs)
        return func(*args, **kwargs) #2
    return f_interna
@debugger
def foo1(x, y=1):
    return x * y
@debugger
def foo2():
    return 2

Output

>>> foo1(5, 4)
Os argumentos foram: (5, 4), {}
20
>>> foo1(1)
Os argumentos foram: (1,), {}
1
>>> foo2()
Os argumentos foram: (), {}
2

Stack (or group of decorators)

In order to use more than one decorator, it is necessary to perform internal packing on the decorator functions as shown in the other answer :

def makebold(fn):
    def pacote():
        return "<b>" + fn() + "</b>"
    return pacote

def makeitalic(fn):
    def pacote():
        return "<i>" + fn() + "</i>"
    return pacote
    
21.08.2014 / 18:13