[Tutor] not understanding a recursion example

Peter Otten __peter__ at web.de
Fri Jan 21 10:43:35 CET 2011


Bill Allen wrote:

> I am not understanding the following code (I did not write it).  It
> demonstrates walking a tree-like data structure using recursion.  It does
> run and produces reasonable output.  I particularly do not understand the
> "traverse.level" statements.  Can anyone give me an idea how this is
> working
> and the principles?  I would like understand recursive calls in Python
> better as I have not used the technique previously.

> def traverse(data):
>     print(' ' * traverse.level + data['text'])
>     for kid in data['kids']:
>         traverse.level += 1
>         traverse(kid)
>         traverse.level -= 1
> 
> if __name__ == '__main__':
>     traverse.level = 1
>     traverse(data)


Functions are objects in python; you can tuck arbitrary attributes onto 
them, and the above uses a function attribute instead of a global variable.
A more standard way to write the above would be

def traverse(data):
    global level
    print(' ' * level + data['text'])
    for kid in data['kids']:
        level += 1
        traverse(kid)
        level -= 1

if __name__ == '__main__':
    level = 1
    traverse(data)

What it does: 
* call traverse with the outermost dictionary
* print the data["text"] value indented by the current global level.
* iterate over the data["kids"] list of dictionaries
* for each entry in that list
    - increment indentation level
    - invoke traverse which will print the data["text"] value.
      (Remember that traverse was called with the current value of kid, so
       in terms of the outer traverse() the inner traverse() is printing
       kid["text"]) Process the kid's kids in the same way.
    - decrement the indentation level

However using global variables is generally a bad practice. 
It is easy to leave them in an inconsistent state, and if you are using 
multiple threads (i. e. invoke traverse() a second time while the first call 
hasn't finished) you'll end up with a big mess.

I would therefore write the traverse function as

def traverse(data, level):
    print(' ' * level + data['text'])
    for kid in data['kids']:
        traverse(kid, level+1)

if __name__ == "__main__":
    traverse(data, 1)

which I think may also be easier to understand.

Peter



More information about the Tutor mailing list