Search code examples
pythontree

Do list comprehension have side effect?


I want to write a preorder recursion of a tree in python. I can use for statement, but if I use list comprehension, I hope to achieve the recursive effect through its side effects, why it doesn't?

this method works:

def preorder(t):
    ret = [label(t)]
    for branch in branches(t):
    ret.extend(preorder(branch))
    return ret

but this didn't give me proper result.

def preorder(t):
    ret = [label(t)]
    a = (ret.extend(preorder(b)) for b in branches(t))
    return ret

with the second method:

T = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])])
preorder(T)

the return is only[1]

Detail of tree ADT

def tree(label, branches=[]):
    """Construct a tree with the given label value and a list of branches."""
    for branch in branches:
        assert is_tree(branch), 'branches must be trees'
    return [label] + list(branches)


def label(tree):
    """Return the label value of a tree."""
    return tree[0]


def branches(tree):
    """Return the list of branches of the given tree."""
    return tree[1:]


Solution

  • Thankyou for everyone on the comment. Here i know

    (expression for item in Sequence )
    

    is a gernerator comperhension, which returns a generator, if i did't call it,(iterate over it), it will do nothing. but list comprehension as below creats a list but also have side-effect:

    [expression for item in Sequence]
    

    to make the () work, i can:

    def preorder(t):
        ret = [label(t)]
        a = (ret.extend(preorder(b)) for b in branches(t))
        for _ in a:
            continue
        return ret
    

    This will give me the right answer as well as:

    def preorder(t):
        ret = [label(t)]
        [ret.extend(preorder(b)) for b in branches(t)]
        return ret
    

    Nevertheless, it is not a good way to rely on the side-effect of a list comprehension, to see detail: Is it Pythonic to use list comprehensions for just side effects?