On Mar 10, 3:58 am, duccio <[EMAIL PROTECTED]> wrote: > Hello! > Someone knows if it's possible to make this __iter__ function with just > one 'yield' intead of two? > Is there some simpler way to make this __iter__ iter through all nodes? > Thanks! > > class Node: > def __init__(self, data=None): > self.childs=[] > self.data=data > def appendNode(self, n): > node=Node(n) > self.childs.append(node) > return node > def __str__(self): > return '<'+str(self.data)+'>' > def __iter__(self): > yield self #1 > for n in self.childs: > for nn in n.__iter__(): > yield nn #2 > > n=Node() > n.appendNode(1).appendNode(2).appendNode(3).appendNode(4) > n.appendNode(11).appendNode(22).appendNode(33).appendNode(44) > for node in n: > print node
Technically, the root node isn't a child node, and thus it shouldn't show up in the iteration. I think a more semantically correct way for this is to have the __str__() returns the current Node + All Descendants Nodes (like the one you wanted for __iter__) and while __iter__ only yields the child nodes (used by the __str__ to iterate through itself), like this: class Node: def __init__(self, data=None): self.childs=[] self.data=data def appendNode(self, n): node=Node(n) self.childs.append(node) return node def __str__(self): ## Returns root node + all descendants return '<%s>\n' % self.data + ''.join(str(child) for child in self) def __iter__(self): ## yields childrens only for n in self.childs: yield n n=Node() n.appendNode(1).appendNode(2).appendNode(3).appendNode(4) ## Note I added the line below for testing branches in ## lower nodes n.childs[0].appendNode(222) n.appendNode(11).appendNode(22).appendNode(33).appendNode(44) print n The missing functionality of returning current Node's name can be easily solved by adding it in another function. The main problem with __iter__ behavior you originally wanted is that it doesn't reflect the nesting behavior of the Node class and you could've been equally well served by using flat data structure if you do that. I smell a bad data structure design here, you'd better revise your design. To reflect the nesting, you could do it like this: class Node: def __init__(self, data=None): self.childs=[] self.data=data def appendNode(self, n): node=Node(n) self.childs.append(node) return node def __str__(self): ## This reflects nesting behavior better return '\n<%s>' % (str(self.data) + ''.join(str(child) for child in self)) ## Uncomment this and Comment the statement above ## for an alternate data structure you might be ## interested in, the format below resembles HTML ## curNode = str(self.data) ## return '\n<%s>%s\n</%s>' % ( ## curNode, ## ''.join(str(child) for child in self), ## curNode) def __iter__(self): for n in self.childs: yield n n=Node() n.appendNode(1).appendNode(2).appendNode(3).appendNode(4) n.childs[0].appendNode(222) n.appendNode(11).appendNode(22).appendNode(33).appendNode(44) print n This changes the data structure quite a lot though, but the data structure is bad from the start. -- http://mail.python.org/mailman/listinfo/python-list