Guy Blanc
Guy Blanc

Reputation: 861

Python: printing all nodes of tree unintentionally stores data

I've created a general tree in python, by creating a Node object. Each node can have either 0, 1, or 2 trees.

I'm trying to create a method to print a list of all the nodes in a tree. The list need not be in order. Here's my simplistic attempt:

def allChildren(self, l = list()):
    l.append(self)
    for child in self.children:
        l = child.allChildren(l)
    return l

The first time I run this method, it works correctly. However, for some reason it is storing the previous runs. The second time I run the method, it prints all the nodes twice. Even if I create 2 separate trees, it still remembers the previous runs. E.g: I create 2 trees, a and b. If I run a.allChildren() I receive the correct result. Then I run b.allChildren() and recieve all of a's nodes and all of b's nodes.

Upvotes: 1

Views: 855

Answers (3)

roman
roman

Reputation: 117370

If you're writing default parameter like l = list(), it will create list when compiling function, so it will one instance of list for all function calls. To prevent this, use None and create new list inside the function:

def allChildren(self, l = None):
    if not l: l = []
    l.append(self)
    for child in self.children:
        l = child.allChildren(l)
    return l

Upvotes: 2

murgatroid99
murgatroid99

Reputation: 20267

You have a mutable value as the default value of your function parameter l. In Python, this means that when you call l.append(self), you are permanently modifying the default parameter.

In order to avoid this problem, set l to a new list every time the function is called, if no list is passed in:

def allChildren(self, l = None):
    if l is None:
        l = list()
    l.append(self)
    for child in self.children:
        l = child.allChildren(l)
    return l

This phenomenon is explained much more thoroughly in this question.

Upvotes: 5

nio
nio

Reputation: 5289

try this:

def allChildren(self, l = None):
    if(l==None):
        l = list()

    l.append(self)
    for child in self.children:
        l = child.allChildren(l)
    return l

And check out this answer for explanation.

Upvotes: 3

Related Questions