Holy s#@%! I think I just understood decorators
#1
Python decorators have been one of those concepts that I could read about over and over again, but just couldn't grok.

But now I think I do.

I was thinking about a particular problematic function, and reckoned to myself, "you know, this would be best solved if I ran some code before the function and then some more code after it as well."

The first idea, quickly rejected, was to write two more functions, then search the code for everywhere the problem function existed and call my new functions before and after each appearance.

The next idea was, well I could edit that other function directly and insert the new code into it. Hey, that seems easy enough! Let's do that.

But then I happened to think, what if that code I wanted to run before and after the problem function was applicable to some other function? How would I go about re-using that code? Re-using code usually calls for making something INTO a function. So why not have a new function that accepts the problem "raw" function as an argument, then calls that "raw" function sandwiched between my new code?

And now here is the genius idea, if I define a third function INSIDE the new function that did that (ie. ran mycode-->rawFunction-->mycode) and then RETURNed that third function, I could simply write
Code:
fixed_func = new_func(raw_func)
and use fixed_func from then on.

Oh wait, damn, how would I handle arguments that need to be passed to raw_func? That would be more complicated, and I was tired, so I almost left it there.

But then I thought I recognised new_func(raw_func).

That's a decorator.

My "new_func" was really a decorator function. Decorator functions take care of arguments being passed to the raw function, so I would simply have to setup my third function to accept *args, **kwargs, and then pass *args, **kwargs to the underlying raw_func.

Ran a quick test to see if I really knew what I thought I knew, and it worked first time.

Code:
def decorator_func(func):

    def third_func(*args, **kwargs):
        print "third_func start"
        func(*args, **kwargs)
        print "third_func end"

    return third_func


@decorator_func
def raw_func(a, b, c, kw_a, kw_b):

    print "\traw_func start"
    print '\t\targ a: ' + str(a)
    print '\t\targ b: ' + str(b)
    print '\t\targ c: ' + str(c)
    print '\t\targ kw_a: ' + str(kw_a)
    print '\t\targ kw_b: ' + str(kw_b)
    print "\traw_func end"

raw_func(1, 2, 3, kw_b= 4, kw_a=5)

So now it has stuck. Turns out I had to arrive at the conclusion following my own path, even though that path was practically a highway beat down by thousands of other pythonistas, and I had read literally a dozen roadmaps already.

So next topic on the list or perpetual confusion: nested list comprehensions!
Reply

Logout Mark Read Team Forum Stats Members Help
Holy s#@%! I think I just understood decorators0