Question

I am new to python and I am now learning decorators. Here is the python decorator example I'm working on:

def makeHtmlTag(tag, *args, **kwds):
    def real_decorator(fn):
        css_class = " class='{0}'".format(kwds["css_class"]) \
                                     if "css_class" in kwds else ""

        def wrapped():
            return "<"+tag+css_class+">" + fn() + "</"+tag+">"
        return wrapped
    return real_decorator

@makeHtmlTag(tag="i", css_class="italic_css")
def hello():
    return "hello world"

print hello()

When I replace function wrapped() with only one line as follows:

return "<"+tag+css_class+">" + fn() + "</"+tag+">"

I get TypeError. Why is that?

Was it helpful?

Solution

A decorator replaces the function object; the syntax is essentially executed as:

def hello():
    return "hello world"
hello = makeHtmlTag(tag="i", css_class="italic_css")(hello)

makeHtmlTag() returns the real_decorator() function, which is called with hello as the argument, and it in turn returns wrapped().

So, after the decorator has been called, hello is now bound to the wrapped() function the real_decorator() nested function returned.

If you replace def wrapped() .. return wrapped with a return statement returning just a string, then hello is now bound to that string and is not a function anymore. You cannot call a string object, leading to your TypeError exception.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top