parameterized iterator?

Jp Calderone exarkun at intarweb.us
Tue Feb 18 22:52:45 EST 2003


On Tue, Feb 18, 2003 at 06:00:11PM -0800, Fortepianissimo wrote:
> Just occurs to me that if I can somehow pass in an argument to specify
> a special ordering when traversing a tree, that'll be perfect. A
> simplified tree node iterator is something like this:
> 
> class Node:
>   def __iter__ (self): return self.postorder()
> 
>   def postorder (self):
>     if hasattr(self,daughters):
>       for d in daughters:
>         for dd in d: yield dd
>     yield self
> 
> 
> daughters is a list of the daughter nodes. This allows me to traverse
> the tree in postorder:
> 
> for node in root:
>   <do something to node>

  And of course, this is effectively the same as:

    for node in root.postorder():
        ...

> 
> Now I want to be able to slip in a new traversal generator to define
> my own way of traversal. The only way I can think of is
> 
> def postorder (node):
>   ...
> 
> def preorder (node):
>   ...
> 
> tFunc=preorder  # change this if necessary
> 
> class Node:
>   def __iter__ (self): return tFunc(self)
> 
> 
> But then again 'tFunc' is immutable and if I change tFunc to another
> traversal generator nothing would change! Unless I make tFunc a list
> (mutable):
> 
> tFunc=[preorder]
> 
> and change and call tFunc[0] instead of tFunc. This is rather ugly. Is
> there any better way to do this?
> 

  Function objects *aren't* immutable, though some of their attributes are. 
But that's beside the point.  The name ``tFunc'' can be -rebound- easily. 
This leaves the function ``preorder'' completely unchanged:

    tFunc = postorder

  However, it has a global effect - every Node object would now yield its
children in postorder, and that may be undesirable (think about interaction
with other modules).

  You could define preorder as another generator on the Node class, and use
the explicit syntax I used above:

    for node in root.preorder():
        ...

  This doesn't conflict at all with postorder, since it bypasses the call to
__iter__ entirely.  This way, the default behavior is whatever your __iter__
defines, but other behavior is easily acheived by calling another function
explicitly.  For extra fun (and possibly), the default order could be a
parameter to __init__.

  Jp

-- 
It is practically impossible to teach good programming style to
students that have had prior exposure to BASIC: as potential
programmers they are mentally mutilated beyond hope of
regeneration.        -- Dijkstra
-- 
 up 10 days, 8:28, 2 users, load average: 0.00, 0.03, 0.00
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20030218/de584118/attachment.sig>


More information about the Python-list mailing list