pythonpython-3.xdata-structuresgraphadjacency-list

Adding Nodes to a graph displays object instead of string (adjacency list)


I'm learning how to create a graph using an adjacency list on Python. My current problem is when trying to add a node to the list, it displays the Node object at 0x0000.... instead of a string. When I try to print out the list, I get TypeError: list indices must be integers or slices, not Node". I can't seem to figure out a way to fix this. Any help would be appreciated!

class Node:
    def __init__(self, name):
        self.name = name
        self.visited = False
        self.adjacency = []

    def addNeighbor(self, v):
        if v not in self.adjacency:
            self.adjacency.append(v)


class DGraph:
    def __init__(self, size=20):
        self.size = size
        self.numNodes = 0
        self.nodeList = [0] * size

    def addNode(self, name):
        """adds new node to graph"""
        if self.numNodes >= self.size:
            raise OverflowError("Graph Size Exceeded")
        newNode = Node(name)
        newNode.name = name
        newNode.addNeighbor(name)
        self.nodeList[self.numNodes] = newNode
        self.numNodes += 1

    def listNodes(self):
        theList = "Nodes: "
        for i in self.nodeList:
            theList += self.nodeList[i]
            theList += ""
        return theList


tree = DGraph()
tree.addNode("A")
tree.addNode('C')
tree.addNode('T')

What the list looks like in the debugger


Solution

  • You can specify string representation of your object by implementing __repr__ See details in the docs and this question Here is a working example (nodeList is fixed too)

    class Node:
        def __init__(self, name):
            self.name = name
            self.visited = False
            self.adjacency = []
    
        def addNeighbor(self, v):
            if v not in self.adjacency:
                self.adjacency.append(v)
    
        def __repr__(self):
            return self.name
    
        def __str__(self):
            return self.name
    
    
    
    class DGraph:
        def __init__(self, size=20):
            self.size = size
            self.numNodes = 0
            self.nodeList = [0] * size
    
        def addNode(self, name):
            """adds new node to graph"""
            if self.numNodes >= self.size:
                raise OverflowError("Graph Size Exceeded")
            newNode = Node(name)
            newNode.name = name
            newNode.addNeighbor(name)
            self.nodeList[self.numNodes] = newNode
            self.numNodes += 1
    
        def listNodes(self):
            theList = "Nodes: "
            for i in self.nodeList:
                theList += str(i)
                theList += " "
            return theList
    
    
    tree = DGraph()
    tree.addNode("A")
    tree.addNode('C')
    tree.addNode('T')
    print(tree.listNodes())
    

    Now debugger will show node names (using__repr__)

    enter image description here

    Such implementation of __repr__ is probably not a good idea unless you enforce uniqueness of node names.

    As a side note, it's nice to follow naming convention in Python