determining the number of output arguments

Peter Otten __peter__ at web.de
Tue Nov 16 13:55:20 EST 2004


Jeremy Bowers wrote:

> On Tue, 16 Nov 2004 17:58:52 +0100, Peter Otten wrote:
>> You could yield Indent/Dedent (possibly the same class) instances
>> whenever the level changes - provided that the length of sequences of
>> nodes with the same depth does not approach one.
> 
> In this case, the depth of the node is multiplied by some indentation
> parameter, or some similar operation, and it occurs in three or places, so
> the duplication of the
> 
> if token == INDENT:
> depth += 1
> elif token == DEDENT:
> depth -= 1
> if depth == 0:
> abort or something
> 
> three or four times was starting to smell itself.

I guess I don't understand, so I wrote a simple example:


DEDENT = object()
INDENT = object()

def _walk(items):
    for item in items:
        if isinstance(item, list):
            yield INDENT
            for child in _walk(item):
                yield child
            yield DEDENT
        else:
            yield item

class Tree(object):
    def __init__(self, data):
        self.data = data
    def __iter__(self):
        for item in _walk(self.data):
            yield item

class WalkBase(object):
    def __call__(self, tree):
        dispatch = {
            DEDENT: self.dedent, 
            INDENT: self.indent
        }
        default = self.default
        for item in tree:
            dispatch.get(item, default)(item)

class PrintIndent(WalkBase):
    def __init__(self):
        self._indent = ""
    def indent(self, node):
        self._indent += "    "
    def dedent(self, node):
        self._indent = self._indent[:-4]
    def default(self, node):
        print self._indent, node
                    
class PrintXml(WalkBase):
    def indent(self, node):
        print "<node>"
    def dedent(self, node):
        print "</node>"
    def default(self, node):
        print "<leaf>%s</leaf>" % node
    def __call__(self, tree):
        print "<tree>"
        super(PrintXml, self).__call__(tree)
        print "</tree>"

if __name__ == "__main__":
    tree = Tree([
        0,
        [1, 2, 3],
        [4, 
            [5, 6, 7],
            [8, [9, 10]]],
        [11],
        12
    ])
    for i, Class in enumerate([PrintIndent, PrintXml]):
        print "%d " % i * 5
        Class()(tree)
          
        
I think taking actions on indent/dedent "events" is easier and simpler than
keeping track of a numerical depth value, and at least the PrintXml example
would become more complicated if you wanted to infer the beginning/end of a
level from the change in the depth.
I do check the depth level twice (isinstance(item, list) and
dispatch.get()), but I think the looser coupling is worth it.
If you are looking for the cool version of such a dispatch mechanism, 
Phillip J. Eby's article

http://peak.telecommunity.com/DevCenter/VisitorRevisited

(found in the Daily Python URL) might be interesting.

Peter






            



More information about the Python-list mailing list