Why different objects have the same attribute in recursion?

Viewed 18

I want to re-construct a Tree From a dictionary. But Here I found that in the recursion, when I create a new Treenode (named node). The ID for node.next_nodes and its parent root.next_nodes are exactly the same. I wonder why this happens?

mydict = {'1': ['21', '22', '23', '24'],
 '21': ['211'],
 '22': ['221', '222'],
 '24': ['241', '242', '243']}

class TreeNode():
    def __init__(self, val = '0', next_nodes = []):
        self.val = val
        self.next_nodes = next_nodes

root = TreeNode('1')
def decode(root):
    if root.val not in mydict:
        return None 
    for node_val in mydict[root.val]:
        node =TreeNode(node_val)
        print(id(root.next_nodes), id(node.next_nodes))
        root.next_nodes.append(node)
        decode(node)
decode(root)

enter image description here

1 Answers

Objects provided as default values are instantiated once when the script is loaded, not every time you call the function. In your case, there is only one next_nodes instance which is reused in every TreeNode object you create. Therefore using mutable objects such as lists as default values is discouraged, because the same list will be re-used every time you call the function. Here is an example:

def append_to_list(val, vals_list = []):
  vals_list.append(val)
  print(vals_list)

>> append_to_list(0)
[0]
>> append_to_list(1)
[0, 1]
>> append_to_list(2)
[0, 1, 2]

each time you invoke append_to_list with a default value, the same list is used. A proper way is to instantiate mutable objects inside the function body to ensure a new object is created every time you call the function. In your case __init__ should be:

def __init__(self, val = '0', next_nodes = None):
    self.val = val
    self.next_nodes = next_nodes if next_node is not None else []
Related