2009-03-30 14 views
7

Nuevo aquí. También soy (muy) nuevo en python e intento entender el siguiente comportamiento. ¿Puede alguien explicarme por qué los dos métodos en este ejemplo tienen una salida diferente?decoradores y métodos de pitón

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() 

Aquí está la salida en mi sistema:

 
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) 

Entonces, ¿por qué la llamada decorada no descienden al nodo nieto? Obviamente estoy perdiendo algo acerca de la sintaxis ...

Respuesta

7

En el decorador, se recorre sobre los hijos del nodo y llamar a la originales, no recursivo method en ellos

method(child, *args, **kwargs) 

por lo que' Solo voy a un nivel profundo. Intente reemplazar esa línea con

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

y obtendrá el mismo resultado que la versión recursiva manual.

+1

Gracias! Sabía que tenía que ser algo así. Intenté esto con la notación @ pero no funcionó (obviamente), y no pude encontrar la sintaxis correcta. Luego logré convencerme a mí mismo de que estaba transformando el método real, por lo que no debería importar. Debo dejar de pensar en ello como macros "adecuadas". –

+0

Creo que este enfoque no hará lo que esperas si se subclasifica el nodo y la subclase tiene su propia versión del método ... – simon