1

I am writing a small tree class that implements a doubly linked list:

class node(object): 
def __init__(self, level=0, pieces=0, parent=None,
             root=None, childNo=None, avgN=2): 

    self.level       = level   # Current level in the tree. Zero = top.
    self.pieces      = pieces  # Number of children. Can be constant or Poisson chosen random.
    self.parent      = parent  # Parent of this node.
    self.child       = {}      # Children of this node. Using a dictionary means
                               # the root could have direct access\
                               # to all children.
    self.childrenID  = {}
    self.myID        = childNo # This node's index in the parents self.child list.

    if (root == None):         # If I'm the root, then hey, I'm the root!
        self.root   = self
    else:
        self.root   = root

    self.avgN          = avgN
    self.numOfChildren = 0
    self.pieces        = self.avgN



def print_all_data(self):
    print "Printing all data for node:",self.myID
    obj_attr = [a for a in dir(n) if not a.startswith('__') and not callable(getattr(n,a))]
    for ob in obj_attr:
        print ob, getattr(n,ob)
    return


# This function acutally adds a child node to this parent.
def add_child_node(self, childno):

    self.numOfChildren        += 1
    if (self.numOfChildren > self.pieces):
        print "Error: number of children exceeds the number of assigned pieces"
        print "       for node:", self.myID

    childno                             = self.compute_new_child_ID(self.level, self.numOfChildren)
    self.childrenID[self.numOfChildren] = childno
    self.child[childno]                 = self.get_new_node(childno)

    return

def get_new_node(self,childno):

    return node(level=self.level+1, parent=self,
                root=self.root, childNo=childno,
                avgN=self.avgN)

def compute_new_child_ID(self, level, childno):
    return (level+1)*100 + childno
def get_child_no_from_child_ID(self, level, childID):
    return childID - (level+1)*100

Note some of the functionality looks duplicated, but those are placeholders for future use.

Now if I make an instance I get:

n = node()
n.print_all_data()

Printing all data for node: None
avgN 2
child {}
childrenID {}
level 0
myID None
numOfChildren 0
parent None
pieces 2
root <__main__.node object at 0x7fb33dc0ae10>

However adding any children results in them inhereting the properties of the parent:

n.add_child_node(0)
n.add_child_node(1)
n.print_all_data()

Printing all data for node: None
avgN 2
child {101: <__main__.node object at 0x7fb33dc46350>, 102: <__main__.node object at 0x7fb33dc460d0>}
childrenID {1: 101, 2: 102}
level 0
myID None
numOfChildren 2
parent None
pieces 2
root <__main__.node object at 0x7fb33dc0ae10>

Here's the child data:

n.child[101].print_all_data()

Printing all data for node: 101
avgN 2
child {101: <__main__.node object at 0x7fb33dc46350>, 102: <__main__.node object at 0x7fb33dc460d0>}
childrenID {1: 101, 2: 102}
level 0
myID None
numOfChildren 2
parent None
pieces 2
root <__main__.node object at 0x7fb33dc0ae10>

Also creating a new node inherits this old instance data:

n2 = node()
n2.print_all_data()

Printing all data for node: None
avgN 2
child {101: <__main__.node object at 0x7fb33dc46350>, 102: <__main__.node object at 0x7fb33dc460d0>}
childrenID {1: 101, 2: 102}
level 0
myID None
numOfChildren 2
parent None
pieces 2
root <__main__.node object at 0x7fb33dc0ae10>

Now I've searched all over StackOverflow and I'm not failing to use init (these are instance attributes) nor am I improperly initializing an immutable dictionary in the function definition (further explained here). I couldn't find any other example in SO that matched my issue, hence the new question. Any assistance is greatly appreciated.

Signal4
  • 153
  • 1
  • 5

1 Answers1

4

Instances are right, you're just printing wrong data.

In the method print_all_data, you're always printing attributes of the instance referenced by the variable n (which is inherited from the higher scope and it always references your "root" node no matter in what instance it's used) instead of printing attributes of the current instance (self reference).

In the method print_all_data, you need something like this (current instance is referenced by the variable self):

obj_attr = [a for a in dir(self)
            if not a.startswith('__') and not callable(getattr(self, a))]
David Ferenczy Rogožan
  • 23,966
  • 9
  • 79
  • 68