<p>I still haven't got my head around decorators in Python.</p>

<p>I've already started using a lot of closures to do things like customize functions and classes in my coding.</p>

<p>Eg.</p>

<pre><code>class Node :
    def __init__(self,val,children) :
        self.val = val
        self.children = children

def makeRunner(f) :
    def run(node) :
        f(node)
        for x in node.children :
            run(x)
    return run

tree=Node(1,[Node(2,[]),Node(3,[Node(4,[]),Node(5,[])])])

def pp(n) : print "%s," % n.val
printTree = makeRunner(pp)
printTree(tree)
</code></pre>

<p>As far as I can see, decorators are just a different syntax for doing something similar. </p>

<p>Instead of </p>

<pre><code>def pp(n) : print "%s," % n.val
printTree = makeRunner(pp)
</code></pre>

<p>I would write :</p>

<pre><code>@makeRunner
def printTree(n) : print "%s," % n.val
</code></pre>

<p>Is this all there is to decorators? Or is there a fundamental difference that I've missed? </p>

Are your examples real code, or just examples?
If they're real code, I think you overuse decorators, probably because of your background (i.e. you are used to other programming languages)
Stage 1: avoiding decorators
```
```
def run(rootnode, func):
    def _run(node): # recursive internal function
        func(node)
        for x in node.children:
            _run(x) # recurse
    _run(rootnode) # initial run
```
```
This run method obsoletes makeRunner. Your example turns to:
```
```
def pp(n): print "%s," % n.val
run(tree, pp)
```
```
However, this ignores completely generators, so…
Stage 2: using generators
```
```
class Node :
    def __init__(self,val,children) :
        self.val = val
        self.children = children

    def __iter__(self): # recursive
        yield self
        for child in self.children:
            for item in child: # recurse
                yield item

def run(rootnode, func):
    for node in rootnode:
        func(node)
```
```
Your example remains
```
```
def pp(n): print "%s," % n.val
run(tree, pp)
```
```
Note that the special method
```
__iter__
```
allows us to use the
```
for node in rootnode:
```
construct. If you don't like it, just rename the
```
__iter__
```
method to e.g.
```
walker
```
, and change the
```
run
```
loop into:
```
for node in rootnode.walker():
```
Obviously, the
```
run
```
function could be a method of
```
class Node
```
instead.
As you see, I suggest you use directly
```
run(tree, func)
```
instead of binding them to the name
```
printTree
```
, but you can use them in a decorator, or you can make use of the
```
functools.partial
```
function:
```
```
printTree= functools.partial(run, func=pp)
```
```
and from then on, you would just
```
```
printTree(tree)
```
```