class Graph:
    def __init__(self, name, children):
        self.name = name
        self.children = children

    def forall(self, checkfunc, nodefunc, leaffunc):
        if self.children == None or self.children == []:
            if checkfunc(self):
                leaffunc(self)
        else:
            if checkfunc(self):
                nodefunc(self)
            for c in self.children:
                c.forall(checkfunc, nodefunc, leaffunc)

    def search(self, name):
        if self.name == name:
            return self
        elif self.children:
            for c in self.children:
                result = c.search(name)
                if result != None:
                    return result
        return None

    def __str__(self):
        return "<Graph: " + self.name + ">"

# -----------------------------------------------

def nocheck(g):
    return True

def beyondC(g):
    return g.name > "C"

def printleaf(g):
    print "Leaf: " + str(g)

def printnode(g):
    print "Node: " + str(g)

# -----------------------------------------------
#    .->- B ->-. 
#   A           D ->- E
#    '->- C ->-'

theKnot = Graph("D", [ Graph("E", None) ])
theGraph = Graph("A", 
            [ Graph("B", [theKnot]),
              Graph("C", [theKnot])] )

print "all"
theGraph.forall(nocheck, printnode, printleaf)

print "beyond C"
theGraph.forall(beyondC, printnode, printleaf)

print "done."