0

I am implementing a basic node object in python. Basically, I implemented a node class with the attribute f_pointers and set it to the default value []. When ever I try to change f_pointers of (lets say) node_a, I will end up changing f_pointers of node_b, which are programmed to be completely unrelated.

I have already solved the problem by instead changing the default value to None and setting up the forward_pointers in __init__. However, I would still like to know how to avoid this problem in the future and possibly learn something new about Python.

For the sake of simplicity, I removed some unnecessary parts of the code.

class Node:
     def __init__(self, f_pointers = []):
          self.f_pointers = f_pointers
     def get_pointers(self):
          return self.f_pointers
     def add_pointers(self, new_pointer):
          self.f_pointers.append(new_pointer)
a = Node()
b = Node()
print(a.get_pointers, b.get_pointers)

>>> [] []

a.add_pointers("a")
print(a.get_pointers, b.get_pointers)

>> ["a"] ["a"]

a.add_pointers("b")
print(a.get_pointers, b.get_pointers)

>> ["a","b"] ["a","b"]

As can be seen, a and b are completely unrelated objects (other than the fact that they are of the same type Node) but will affect each other. Why does this happen?

Mk43v3r
  • 57
  • 1
  • 1
  • 5
  • Your problem is called "mutable default arguments". Read about it in the question I linked to as a duplicate. – Ralf Apr 02 '19 at 10:22

2 Answers2

0

It's because you are referencing to the same list (the one instantiated in the __init__ default params list definition like __init__(self, f_pointers=[]). What happens is that when you say in the __init__ method code block that self.f_points = f_pointers you are basically referencing the same list every time you instantiate a new Node object.

The reasons are explained further here

What you do want to do instead is instantiate a new list for every init like:

def __init__(self, f_pointers=None):
    self.f_pointers = []
andreihondrari
  • 5,743
  • 5
  • 30
  • 59
0

You should do it like this.

class Node:
    def __init__(self, f_pointers=None):
        if f_pointers:
            self.f_pointers = f_pointers
        else:
            self.f_pointers = []
    def get_pointers(self):
        return self.f_pointers
    def add_pointers(self, new_pointer):
        self.f_pointers.append(new_pointer)

a = Node()
b = Node()

print(a.get_pointers(), b.get_pointers())

a.add_pointers("a")
print(a.get_pointers(), b.get_pointers())

You get this kind of behavior because in your case a.f_pointers and b.f_pointers is the same list, which was generated, when you described your class Node.
So a.f_pointers is b.f_pointers == True in your case

Oskar
  • 21
  • 4