Python loop | "do-while" over the tree

Is there a more pythonic way to link this loop ?:

while True:
    children = tree.getChildren()
    if not children:
        break
    tree = children[0]

      

UPDATE: I think this syntax is probably what I will be working with:

while tree.getChildren():
    tree = tree.getChildren()[0]

      

+2


source to share


5 answers


children = tree.getChildren()
while children:
    tree = children[0]
    children = tree.getChildren()

      

It would be easier to suggest something if I knew which collection you are working with. In a good api, you could probably do something like



while tree.hasChildren():
    children = tree.getChildren()
    tree = children[0]

      

+4


source


(My first answer suggested using it iter(tree.getChildren, None)

directly, but that won't work since we don't call the same function all the time tree.getChildren

.)

To fix this, I propose a solution using lambda unrelated to its variables as a possible workaround. I think at the moment this solution is no better than any other previously posted:

You can use iter () in its second sentinel form using the weird lamda binding:



for children in iter((lambda : tree.getChildren()), None):
    tree = children[0]

      

(This assumes getChildren () returns None

when there are no children, but needs to be replaced with any return value ( []

?).)

iter(function, sentinel)

calls the function repeatedly until it returns the breakpoint value.

+2


source


Do you really only want the first branch? I'm going to assume that you don't, and that you want the whole tree. First I would do this:

def allitems(tree):
    for child in tree.getChildren():
        yield child
        for grandchild in allitems(child):
            yield grandchild

      

This will go through the entire tree. Then you can simply:

for item in allitems(tree):
    do_whatever_you_want(item)

      

Pythonic, simple, clean, and since it uses generators won't use much memory even for huge trees.

+1


source


I think your code is fine. If you really wanted it, you can wrap the whole thing in try / except:

while True:
    try:    
        tree = tree.getChildren()[0]
    except (IndexError, TypeError):
        break

      

IndexError

will work if it getChildren()

returns an empty list when there are no children. If it returns False

either 0

or None

or some other invalid false value TypeError

will handle the exception.

But this is another way to do it. Again, I don't think the Pythonistas will be looking for you for the code you already have.

0


source


Without further testing, I believe this should work:

try:    while True: tree=tree.getChildren()[0]
except: pass

      

You can also override the __getitem__()

(parenthesis operator) in the class Tree

for further optimization.

try:    while True: tree=tree[0]
except: pass

      

0


source







All Articles