Hello,

I have some code that passes arguments between functions, though I am failing to understand why my code isn't working. This is the relevant section of my Dijkstra's algorithm code:

def network():
    f = open ('network.txt', 'r')
    network = [[int(node) for node in line.split(',')] for line in f.readlines()]
    print network

    return network

The above function reads in the distances between the nodes from a text file, which is hoped would then be able to be read in to the function below which finds the nearest neighbour of each node:

#find the nearest neighbour to a particular node
def nearestNeighbour(currentNode, network):
     nearestNeighbour = []
     nodeIndex = 0
     for node in network[currentNode]:
     #for node in network[currentNode]:
          if node != 0 & currentNode.visited == false:
             nearestNeighbour.append(nodeIndex)
             nodeIndex +=1

     return nearestNeighbour

However, I am getting this error message:

for node in network:
TypeError: 'function' object is not iterable

Any thoughts would be greatly appreciated

network ---> network()
Also it's not a very good idea to give variables the same name as your function. A good name for the function would be load_network()

Edited 5 Years Ago by Gribouillis: n/a

network ---> network()
Also it's not a very good idea to give variables the same name as your function. A good name for the function would be load_network()

Hi, I have changed the variable 'network' to 'theNetwork' though I am now getting this error:

for node in theNetwork[currentNode]:
TypeError: 'function' object is not subscriptable

I'm probably overseeing something simple, I will include all of my code, though I don't think it has any bearing:

infinity = 1000000
invalid_node = -1
startNode = 0

#Values to assign to each node
class Node:
     distFromSource = infinity
     previous = invalid_node
     visited = False

#read in all network nodes
def network():
    f = open ('network.txt', 'r')
    theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
    print theNetwork

    return theNetwork

#for each node assign default values    
def populateNodeTable(): 
    nodeTable = []
    index = 0
    f = open('network.txt', 'r')
    for line in f: 
      node = map(int, line.split(',')) 
      nodeTable.append(Node())
      
      print "The previous node is " ,nodeTable[index].previous 
      print "The distance from source is " ,nodeTable[index].distFromSource 
      index +=1
    nodeTable[startNode].distFromSource = 0 

    return nodeTable

Hi, I have changed the variable 'network' to 'theNetwork' though I am now getting this error:

for node in theNetwork[currentNode]:
TypeError: 'function' object is not subscriptable

I'm probably overseeing something simple, I will include all of my code, though I don't think it has any bearing:

infinity = 1000000
invalid_node = -1
startNode = 0

#Values to assign to each node
class Node:
     distFromSource = infinity
     previous = invalid_node
     visited = False

#read in all network nodes
def network():
    f = open ('network.txt', 'r')
    theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
    print theNetwork

    return theNetwork

#for each node assign default values    
def populateNodeTable(): 
    nodeTable = []
    index = 0
    f = open('network.txt', 'r')
    for line in f: 
      node = map(int, line.split(',')) 
      nodeTable.append(Node())
      
      print "The previous node is " ,nodeTable[index].previous 
      print "The distance from source is " ,nodeTable[index].distFromSource 
      index +=1
    nodeTable[startNode].distFromSource = 0 

    return nodeTable

It seems that the line causing the error appears nowhere in your code !

It seems that the line causing the error appears nowhere in your code !

Silly me, I forgot to paste the main function in (was buried under uncommented code) :$ - here is the missing code:

currentNode = startNode

if __name__ == "__main__":
    populateNodeTable()
    network()
    nearestNeighbour(currentNode, theNetwork)
    #tentativeDistance(currentNode,populateNodeTable())

Well progress has been made, though it's now complaining that 'theNetwork has not been defined' even though I have defined it in my network function:

nearestNeighbour(currentNode, theNetwork)
NameError: name 'theNetwork' is not defined

Silly me, I forgot to paste the main function in (was buried under uncommented code) :$ - here is the missing code:

currentNode = startNode

if __name__ == "__main__":
    populateNodeTable()
    network()
    nearestNeighbour(currentNode, theNetwork)
    #tentativeDistance(currentNode,populateNodeTable())

Well progress has been made, though it's now complaining that 'theNetwork has not been defined' even though I have defined it in my network function:

nearestNeighbour(currentNode, theNetwork)
NameError: name 'theNetwork' is not defined

Names defined in a function don't exist outside the function. They are called local variables. Use the value returned by the function

if __name__ == "__main__":
    populateNodeTable()
    theNetwork = network() # here we define a variable (it's not the same theNetwork)
    nearestNeighbour(currentNode, theNetwork)
    #tentativeDistance(currentNode,populateNodeTable())

Edited 5 Years Ago by Gribouillis: n/a

Names defined in a function don't exist outside the function. They are called local variables. Use the value returned by the function

if __name__ == "__main__":
    populateNodeTable()
    theNetwork = network() # here we define a variable (it's not the same theNetwork)
    nearestNeighbour(currentNode, theNetwork)
    #tentativeDistance(currentNode,populateNodeTable())

Ah ok, I see. I have one last question, I am now getting this error message:

if node != 0 & currentNode.visited == false:
AttributeError: 'int' object has no attribute 'visited'

I understand that it's not possible to return more than one argument from a function, though I have tried to implement this code but unsurprisingly it failed:

#find the nearest neighbour to a particular node
def nearestNeighbour(currentNode, theNetwork, [B]nodeTable[/B]):
     nearestNeighbour = []
     nodeIndex = 0
     for node in theNetwork[currentNode]:
          if node != 0 & currentNode.visited == false:
             nearestNeighbour.append(nodeIndex)
             nodeIndex +=1

     return nearestNeighbour

Is there a way of 'connecting' the values in my class Node, populateNodeTable and nearestNeighbour functions?

Warning! In python, one writes if node != 0 [b]and[/b] currentNode.visited == false the & operator is something else.

Yes there are ways of connecting all these data. You are in a situtation where there are 2 ways to refer to the nodes: their index and the Node object that you are creating. A way to handle this is to have only one way to refer to the nodes, otherwise your code becomes easily a mess.

So the index could become an attribute of the node object like this

class Node:
    def __init__(self, index):
        self.index = index
        self.distFromSource = infinity
        self.previous = None
        self.visited = False
        self.neighbours = []

Then the network, instead of being a list of lists of integers, could be a list of Node objects.
You can even define a Network class, which gives you a way of connecting the functions

class Network(list):
    def __init__(self, filename):
        list.__init__(self)
        with open(filename) as filein:
            lines = filein.readlines()
            self[:] = [Node(i) for i in range(len(lines))] # create the Nodes
            for i, line in enumerate(lines):
                self[i].neightbours[:] = [self[j] for j in (int(n) for n in line.split(","))]

    def nearestNeighbour(self, node):
        etc...

Edited 5 Years Ago by Gribouillis: n/a

Warning! In python, one writes if node != 0 [b]and[/b] currentNode.visited == false the & operator is something else.

Yes there are ways of connecting all these data. You are in a situtation where there are 2 ways to refer to the nodes: their index and the Node object that you are creating. A way to handle this is to have only one way to refer to the nodes, otherwise your code becomes easily a mess.

So the index could become an attribute of the node object like this

class Node:
    def __init__(self, index):
        self.index = index
        self.distFromSource = infinity
        self.previous = None
        self.visited = False
        self.neighbours = []

Then the network, instead of being a list of lists of integers, could be a list of Node objects.
You can even define a Network class, which gives you a way of connecting the functions

class Network(list):
    def __init__(self, filename):
        list.__init__(self)
        with open(filename) as filein:
            lines = filein.readlines()
            self[:] = [Node(i) for i in range(len(lines))] # create the Nodes
            for i, line in enumerate(lines):
                self[i].neightbours[:] = [self[j] for j in (int(n) for n in line.split(","))]

    def nearestNeighbour(self, node):
        etc...

I shall give that a try, thanks a lot!

This question has already been answered. Start a new discussion instead.