0

In the code below, I define a Node class which when instantiated, should have an empty "childarr" property. Then, I instantiate the class and pass it to the method, "expnd". This adds three new node to the childarr array. As expected, the first print statement shows that the length of the childarr of the "node" instance is 3. But now, I instantiate a new instance of the "Node" class from scratch. Since I specified in the init method of the class that if nothing is passed for this variable, it should be an empty array, I was expecting nn to have an empty childarr property. However, the second print statement shows it actually has three children as well.

It's very confusing to me why "nn" is being affected by some code that happened before it was instantiated and has nothing to do with it.

Does anyone know of the reason for this behavior and what I'm missing in terms of best practice?

class Node():
    def __init__(self, childarr=[]):
        self.childarr = childarr

def expnd(node):
    for i in range(3):
        newnode = Node()
        node.childarr.append(newnode)

node=Node()
expnd(node)
print("Length of child array of expanded node:" + str(len(node.childarr)))

nn = Node()
print("Length of child array of new, unrelated node:" + str(len(nn.childarr)))
Rohit Pandey
  • 2,443
  • 7
  • 31
  • 54
  • 2
    This a very common mistake. You shouldn't initialize your `childarr`'s default value as `[]`. In this case, all instances will share the same instance of list. – Sraw Dec 03 '18 at 07:22
  • 2
    Note that this same error can occur outside methods: https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument – torek Dec 03 '18 at 07:47

1 Answers1

1

The problem is that you instantiate all "empty" childarrs with the same empty list instance, created in the definition of __init__. One way to change this behaviour:

class Node():
    def __init__(self, childarr=None):
        self.childarr = childarr or []

def expnd(node):
    for i in range(3):
        newnode = Node()
        node.childarr.append(newnode)

node=Node()
expnd(node)
print("Length of child array of expanded node:" + str(len(node.childarr)))

nn = Node()
print("Length of child array of new, unrelated node:" + str(len(nn.childarr)))

Result:

Length of child array of expanded node:3
Length of child array of new, unrelated node:0
andersource
  • 799
  • 3
  • 9