Watson Aname
Watson Aname

Reputation:

python decorators and methods

New here. Also I'm (very) new to python and trying to understand the following behavior. Can someone explain to me why the two methods in this example have different output?

def map_children(method):
    def wrapper(self,*args,**kwargs):
        res = method(self,*args,**kwargs)
        for child in self._children:
            method(child,*args,**kwargs)            
        return res
    return wrapper

class Node(object):

    def __init__(self,name,parent=None):
        self._namestring = name
        if parent:
            self._parent = parent

        self._children = []

    @map_children
    def decorated(self):
        if hasattr(self,'_parent'):
            print '%s (child of %s)'%(self._namestring,self._parent._namestring)
        else:
            print '%s'% self._namestring

    def undecorated(self):
        if hasattr(self,'_parent'):
            print '%s (child of %s)'%(self._namestring,self._parent._namestring)
        else:
            print '%s'% self._namestring

        for child in self._children:
            child.undecorated()


def runme():
    parent = Node('parent')

    child1 = Node('child1',parent)
    child2 = Node('child2',parent)
    grandchild = Node('grandchild',child1)
    child1._children.append(grandchild)
    parent._children.append(child1)
    parent._children.append(child2)

    print '**********result from decorator**********'
    parent.decorated()

    print '**********result by hand**********'
    parent.undecorated()

Here is the output on my system:

In[]:testcase.runme()
**********result from decorator**********
parent
child1 (child of parent)
child2 (child of parent)
**********result by hand**********
parent
child1 (child of parent)
grandchild (child of child1)
child2 (child of parent)

So why does the decorated call never descend to the grandchild node? I'm obviously missing something about the syntax...

Upvotes: 8

Views: 6966

Answers (1)

dF.
dF.

Reputation: 75785

In the decorator, you are looping over the node's children and calling the original, non-recursive method on them

method(child, *args, **kwargs)

so you'll only go one level deep. Try replacing that line with

map_children(method)(child, *args, **kwargs)

and you'll get the same output as the manual recursive version.

Upvotes: 7

Related Questions