'str' object has no attribute / error calling a dictionary - python

I have a class with a function that adds an edge to the graph, according to the input given. For example: if the input is add James Larry 1, an edge will be added between James and Larry with the weight (intimacy level) 1. The graph is a dictionary of sets, so, the keys are the node and the values (sets) are the edges.
So, this function has as parameters: the source, the destination and the weight. The class is represented below:
class DiGraph(object):
# Create an empty graph.
def __init__(self):
## A dictionary that stores an entry of a node, as the key, and a set of outgoing edges
# (destination node, weight) from the node, as its value.
self.graph = {}
## Total number of edges in the graph.
self.__numEdges = 0
## The largest edge distance.
# self.__infinity = sys.maxint
self.__infinity = sys.maxsize
## Holds the path from a source node to a given node.
self.__pathToNode = None
## Accumulated distance from source to a node.
self.__dist = None
### (...)
def addEdge(self, src, dst, c=1):
if ( src == None or dst == None or c <= 0 or src == dst ):
return False
# the edge set of src
eSet = self.graph.get(src)
e = Edge(dst,c) # new edge
if eSet == None:
# no edge starting at src, so create a new edge set
eSet = set()
self.__numEdges += 1
else:
ed = self.getEdge(src,dst)
if ( ed != None ):
ed.setCost(c)
return True
else:
self.__numEdges += 1
eSet.add(e) # a set does not have duplicates
self.graph[src] = eSet
if not self.hasVertex(dst):
self.addVertex(dst)
return True
I am trying to implement this code:
import DiGraph
#Create an empty graph
def main():
aGraph = {}
f = open("infile.txt")
contents = f.read()
lines = contents.splitlines()
word = []
for line in lines:
word.append(line.split())
for i in range(len(word)):
if word[i][0] == 'add':
aGraph = DiGraph.DiGraph.addEdge(word[i][1], word[i][2], int(word[i][3]))
return aGraph
grafo = main()
And the first line of the file is: add James Larry 1
This error is being showed to me when I try to run this code:
Traceback (most recent call last):
File "C:/.../SocialGraph.py", line 24, in
grafo = main()
File "C:/.../SocialGraph.py", line 20, in main
aGraph = DiGraph.DiGraph.addEdge(word[i][1], word[i][2], int(word[i][3]))
File "C:...\DiGraph.py", line 156, in addEdge
eSet = self.graph.get(src)
AttributeError: 'str' object has no attribute 'graph'
What can I do to correct this?

DiGraph.DiGraph.addEdge(word[i][1],
You call this as a static method. 'word[i][1]' becomes 'self'.

You implement addEdge as an instance method so that you have to create an instance to use it. Like so:
# create DiGraph instance
diGraph = DiGraph.DiGraph()
for i in range(len(word)):
if word[i][0] == 'add':
aGraph = diGraph.addEdge(word[i][1], word[i][2], int(word[i][3]))

Related

Object is not callable?

Hi everyone I cannot figure out how to fix this issue and from my knowledge it's because of the attributes of the object's I am using.
For your information, I am making a graph in Python and the graph needs to check if all the vertices and edges are connected.
class graph(object):
def __init__(self, gdict=None):
if gdict == None:
gdict = {}
self.gdict = gdict
# return the keys of the dictionary list, or vertices
def getVertice(self):
return list(self.gdict.keys())
# this allows us to obtain the edges for the graph
# or "values" of the dict key
def getEdges(self):
return self.generate_edges()
def addVertex(self, vertex):
if vertex not in self.gdict:
self.gdict[vertex] = []
def addEdge(self, edge):
edge = set(edge)
(vertex1, vertex2) = tuple(edge)
if vertex1 in self.gdict:
self.gdict[vertex1].append(vertex2)
else:
self.gdict[vertex1] = [vertex2]
# this generates a list of all edges for the vertices
def generate_edges(self):
edges = []
for vertex in self.gdict:
for neighbour in self.gdict[vertex]:
if (neighbour, vertex) not in edges:
edges.append((vertex, neighbour))
return edges
def find_path(self, startVertex, endVertex, paths=None):
if paths == None:
paths = []
graphs = self.gdict
paths = paths + [startVertex]
if startVertex == endVertex:
return paths
if startVertex not in graphs:
return None
for vertex in graphs[startVertex]:
if vertex not in paths:
extendedPath = self.find_path(vertex, endVertex, paths)
if extendedPath:
return extendedPath
return None
def findAllPath(self, startVertex, endVertex, paths=None):
if paths is None:
paths = []
graphs = self.gdict
paths = paths + [startVertex]
if startVertex == endVertex:
return [paths]
if startVertex not in graphs:
return []
paths = []
for vertex in graphs[startVertex]:
if vertex not in paths:
extendedPath = self.find_path(vertex, endVertex, paths)
for p in extendedPath:
paths.append(p)
return paths
def findisovertices(self): ##reword this
""" returns a list of isolated vertices. """
graphs = self.gdict
iso = []
for vertex in graphs:
print(iso, vertex)
if not graphs[vertex]:
iso += [vertex]
return iso
def isConnected(self, verticesMet=None, startVertex=None):
if verticesMet is None:
verticesMet = set()
gdict = self.gdict
vertices = self.gdict()
if not startVertex:
startVertex = vertices[0]
verticesMet.add(startVertex)
if len(verticesMet) != len(vertices):
for vertex in gdict[startVertex]:
if vertex not in verticesMet:
if self.isConnected(verticesMet, vertex):
return True
else:
return True
return False
# this function prints the nodes/vertices in the graph
def completeGraph(self):
Vertex = len(self.gdict.keys())
Edges = len(self.gdict.values())
answer = 2.0 * Edges / (Vertex * (Vertex - 1))
return answer
graph_elements = ({"a": ["d", "f"],
"b": ["c"],
"c": ["b", "c", "d", "e"],
"d": ["a", "c"],
"e": ["c"],
"f": ["a"],
"z": []
})
g = graph(graph_elements)
print("Our vertices are: \n", g.getVertice())
print("#1 | Generate list of all edges: \n", graph.generate_edges(g))
##2 Function to calculate isolated nodes of graph.
isolated = graph.findisovertices(g)
print("#2 | Find isolated nodes:\n", isolated)
# 3. Function to find a path from a start vertex to an end vertex
path = graph.find_path(g, "a", "c")
print("#3 | Find a path function: \n", path)
# 4. Function to find all the paths between a start vertex to an end vertex
allPaths = graph.findAllPath(g, "a", "e")
print("#4 | All paths function:\n", allPaths)
# 5. Function to check if graph is connected
connect = graph(g)
print("#5 | Connected graph function \n", connect.isConnected(g))
and I keep receiving the following error:
Traceback (most recent call last):
File "graphsAssign6.py", line 160, in <module>
print("#5 | Connected graph function \n", connect.isConnected(g))
File "graphsAssign6.py", line 95, in isConnected
vertices = self.gdict()
TypeError: 'graph' object is not callable
def isConnected(self, verticesMet=None, startVertex=None):
if verticesMet is None:
verticesMet = set()
gdict = self.gdict
vertices = self.getVertice()
if not startVertex:
startVertex = vertices[0]
verticesMet.add(startVertex)
if len(verticesMet) != len(vertices):
for vertex in gdict[startVertex]:
if vertex not in verticesMet:
if self.isConnected(verticesMet, vertex):
return True
else:
return True
return False
# 5. Function to check if graph is connected
print("#5 | Connected graph function \n", g.isConnected())
Don't make a new connect = graph(g). Your isConnected should work within g. Also, you shouldn't get your vertices with self.gdict(). It doesn't make sense and you already have a function named getVertice for that job.

Facing a syntactic problem in Directed Acyclic Graph Python

Here I'm using DAG to solve Job scheduling problem.
from collections import defaultdict
class JobGraph:
def __init__(self):
self.graph = defaultdict(list)
self.indegree = defaultdict(int)
self.visited = set()
def addEdge(u, v):
self.graph(u).append(v)
try:
self.indegree[v] += 1
except:
self.indegree[v] = 1
def topologicalSort(jobs, deps, queue = [], order = [], flag = 0):
# Write your code here.
if flag == 0:
g = JobGraph()
for dep in deps:
g.addEgde(dep[0], dep[1])
for job in jobs:
if g.indegree[job] == 0:
queue.append(job)
order.append(queue[0])
root = queue[0]
del queue[0]
for neighbour in self.graph[root]:
g.indegree[neighbour] -= 1
if g.indegree[neighbour] == 0 and neighbour not in g.visited:
queue.append(neighbour)
if len(queue) == 0:
return order
else:
topologicalSort(jobs, deps, queue, order, 1)
But the error I'm getting is
'JobGraph' object has no attribute 'addEgde'
Traceback (most recent call last):
File "/tester/json_wrapper.py", line 8, in run
actual = program.topologicalSort(inputs["jobs"][:], aelib.deepCopy(inputs["deps"]))
File "/tester/program.py", line 20, in topologicalSort
g.addEgde(dep[0], dep[1])
AttributeError: 'JobGraph' object has no attribute 'addEgde'
I know it's a syntactic issue I just don't know how to solve it
Input example
jobs = [1,2,3,4]
deps = [[1,2], [1,3], [3,2], [4,2], [4,3]]
Your code seems to have other problems, but the one that's causing this error is simple and obvious. You define a method named addEdge like this:
def addEdge(u, v):
but then you are calling a method named addEgde, like this:
g.addEgde(dep[0], dep[1])
You simply have a typo. addEdge != addEgde. You've reversed the g and the d.
BTW, the signature of that method should probably be:
def addEdge(self, u, v):

Building a Binary Search Tree from a file

I have a text file of lines in the format
2 0 0
7 0 0
4 1 1
10 0 0
9 0 1
8 1 1
These lines represent the data in a binary search tree where the first element is the node data, the second is whether or not a left child exists ( 0 if no, 1 if yes) and the third is whether or not a right child exists (0 if no, 1 if yes)
I have a class called "BinarySearchTree" which has the following initialization function
def __init__(self, value=None):
# Initializes the tree with a value node, a left child and a right child
self.leftChild = None
self.rightChild = None
self.height = 1
self.value = value
I also have a stack class with the following "push" and "pop" functions:
def push(self, item):
# Adds an item to the beginning of the stack
ending = self.stack
self.stack = [item] + [ending]
def pop(self):
# Removes and returns the first element from the stack
if self.isEmpty():
return None
top_element = self.stack[0]
self.stack = self.stack[1:]
return top_element
I am trying to create a binary search tree instance from the lines in the text file and using the stack class. So far I have:
def loadTreeFromFile(filename):
binarySearchTree = stack.Stack()
with open(filename) as file:
# gets a list containing only the elements in the txt file
for level in file.readlines():
nodeInfo = level.rstrip().split()
data, lc, rc = int(nodeInfo[0]), int(nodeInfo[1]), int(nodeInfo[2])
print(data, lc, rc)
if rc == 1:
right_tree = binarySearchTree.pop()
if lc == 1:
left_tree = binarySearchTree.pop()
newTree = BinarySearchTree(data)
if rc == 1:
newTree.rightChild = right_tree
if lc == 1:
newTree.leftChild = left_tree
binarySearchTree.push(newTree)
return newTree
I am running into the problem when I try to display the BST, I get 8: [[[<__main__.BinarySearchTree object at 0x1033e4390>, []]], 9: [None, 10: [None, None]]] (I have a display function written for the BST class so this is not the problem) AND when I try to do anything with this newly created BST (such as get the depth, search it, etc), I get errors. Any help is much appreciated, thanks .

Classification TypeError: 'int' object is not subscriptable

I am making an id3 classifier using entropy for cost calculation, but when I am splitting categorical attributes I keep getting a TypeError: 'int' object is not subscriptable, when running the line: child = [x for x in records if x[attr_name] in a_i], in the method: split_categorical
The dataset:
sunny, 85, 85, false, No
sunny, 80, 90, true, No
overcast, 83, 78, false, Yes
rain, 70, 96, false, Yes
rain, 68, 80, false, Yes
rain, 65, 70, true, No
overcast, 64, 65, true, Yes
sunny, 72, 95, false, No
sunny, 69, 70, false, Yes
rain, 75, 80, false, Yes
sunny, 75, 70, true, Yes
overcast, 72, 90, true, Yes
overcast, 81, 75, false, Yes
rain, 71, 80, true, No
full code:
import csv
import math
from statistics import median, mode
from collections import Counter
from enum import Enum
class AttrType(Enum):
cat = 0 # categorical (qualitative) attribute
num = 1 # numerical (quantitative) attribute
target = 2 # target label
class NodeType(Enum):
root = 0
internal = 1
leaf = 2
class SplitType(Enum):
bin = 0 # binary split
multi = 1 # multi-way split
class Attribute(object):
def __init__(self, label, type):
assert type in AttrType
self.label = label
self.type = type
self.stat = None # holds mean for numerical and mode for categorical attributes
class Splitting(object):
def __init__(self, attr, infogain, split_type, cond, splits):
self.attr = attr # attribute ID (index in ATTR)
self.infogain = infogain # information gain if splitting is done on this attribute
self.split_type = split_type # one of SplitType
self.cond = cond # splitting condition, i.e., values on outgoing edges
self.splits = splits # list of training records (IDs) for each slitting condition
class Node(object):
def __init__(self, id, type, parent_id, children=None, edge_value=None, val=None, split_type=None, split_cond=None):
self.id = id # ID (same as the index in DT.model list)
self.type = type # one of NodeType
self.parent_id = parent_id # ID of parent node (None if root)
self.children = children # list of IDs of child nodes
self.edge_value = edge_value # the value of the incoming edge (only if not root node)
self.val = val # if root or internal node: the attribute that is compared at that node; if leaf node: the target value
self.split_type = split_type # one of SplitType
self.split_cond = split_cond # splitting condition (median value for binary splits on numerical values; otherwise a list of categorical values (corresponding to child nodes))
self.infogain = infogain
def append_child(self, node_id):
self.children.append(node_id)
# input filename and data format are hard-coded here
INFILE = "data/example.csv"
# attribute labels types (same order as in the file!)
ATTR = [Attribute("Outlook", AttrType.cat), Attribute("Temperature", AttrType.num),
Attribute("Humidity", AttrType.num), Attribute("Windy", AttrType.cat), Attribute("Play?", AttrType.target)]
IDX_TARGET = len(ATTR) - 1 # index of the target attribute (assuming it's the last)
#main class:
class DT(object):
def __init__(self):
self.data = None # training data set (loaded into memory)
self.model = None # decision tree model
self.default_class = None # default target class
def __load_data(self):
with open(INFILE) as csvfile:
self.data = []
csvreader = csv.reader(csvfile, delimiter=',')
for row in csvreader:
rec = []
for i in range(len(ATTR)):
val = row[i].strip()
# convert numerical attributes
if ATTR[i].type == AttrType.num: # Note that this will break for "?" (missing attribute)
val = float(val)
rec.append(val)
self.data.append(rec)
# self.data.append([element.strip() for element in row]) # strip spaces
def __entropy(self, records):
"""
Calculates entropy for a selection of records.
:param records: Data records (given by indices)
"""
# TODO records er en liste med index til hver record
#Entropy of a list of records associated with a node.
dat = {key:self.data[key] for key in records}
count = Counter([x[4] for x in dat.values()]) #target=4="Play?"
return sum([(-freq / len(dat)) * math.log(freq / len(dat), 2) for freq in count.values()])
#return sum([(-freq / len(self.data)) * math.log(freq / len(self.data), 2) for freq in records])
def split_categorical(self, records, attr_name, values_sets):
print("Splitting by {}".format(attr_name))
children = []
for a_i in values_sets: # for each subset of possible values\n",
child = [x for x in records if x[attr_name] in a_i]
children.append(child)
# e.g. if values_sets = [{\"sunny\"}, {\"overcast\", \"rain\"}], and atr_name = \"Outlook\"\n",
# then, in the 2nd iteration, a_i = {\"overcast\", \"rain\"},\n",
# so child = list of records for which the value in \"Outlook\" attr is in {\"overcast\", \"rain\"}\n",
# We also print the entropy for each child\n",
print("Child condition: {}Size = {}Entropy = {}".format(a_i, len(child), entropy(child)))
return children
def split_numeric_binary(self, records, attr_name, splitting_point):
print("Splitting by {}".format(attr_name))
children = [[x for x in records if x[attr_name] <= splitting_point],
[x for x in records if x[attr_name] > splitting_point]]
# We also print the entropy for each child
print("'Less-or-equal-than' child. Size = {}Entropy = {}".format(len(children[0]), entropy(children[0])))
print("'Greater-than' child. Size = {}Entropy = {}".format(len(children[1]), entropy(children[1])))
return children
def infogain(self, parent_records, children_records):
#param parent_records: list of records associated with the parent node.
#param children_records: list of lists, each list contains all the records associated with one child.
entropy_p = entropy(parent_records)
return entropy_p - sum([(len(child_records) / len(parent_records)) * entropy(child_records)
for child_records in children_records])
def __find_best_attr(self, attrs, records):
"""
Finds the attribute with the largest gain.
:param attrs: Set of attributes
:param records: Training set (list of record ids)
:return:
"""
entropy_p = self.__entropy(records) # parent's entropy
splittings = [] # holds the splitting information for each attribute
for a in attrs:
assert ATTR[a].type in AttrType
splits = {} # record IDs corresponding to each split
children = []
# splitting condition depends on the attribute type
if ATTR[a].type == AttrType.target: # skip target attribute
continue
elif ATTR[a].type == AttrType.cat: # categorical attribute
# multi-way split on each possible value
split_mode = SplitType.multi
# each possible attr value corresponds to a split (indexed with categorical labels)
# Note: it's important to consider attr values from the entire training set
split_cond = set([self.data[idx][a] for idx in range(len(self.data))])
# TODO collect training records for each split
# `splits[val]` holds a list of records for a given split,
# where `val` is an element of `split_cond`
#split_categorical og legg til resultat i splits
children = self.split_categorical(records,a,split_cond)
for i, val in enumerate(split_cond):
splits[val]=children[i] #get records for given split
elif ATTR[a].type == AttrType.num: # numerical attribute => binary split on median value
split_mode = SplitType.bin
split_cond = self.__median(a) # (i.e., if less or equal than this value)
# TODO collect training records for each split (in `splits`)
children = self.split_numeric_binary(records, a, split_cond)
for i, val in enumerate(split_cond):
splits[val]=children[i]
# TODO compute gain for attribute a
infogain = self.infogain(records, children)
splitting = Splitting(a, infogain, split_mode, split_cond, splits)
splittings.append(splitting)
# find best splitting
best_splitting = sorted(splittings, key=lambda x: x.infogain, reverse=True)[0]
return best_splitting
def __add_node(self, parent_id, node_type=NodeType.internal, edge_value=None, val=None, split_type=None,
split_cond=None):
"""
Adds a node to the decision tree.
:param parent_id:
:param node_type:
:param edge_value:
:param val:
:param split_type:
:param split_cond:
:return:
"""
node_id = len(self.model) # id of the newly assigned node
if not self.model: # the tree is empty
node_type = NodeType.root
node = Node(node_id, node_type, parent_id, children=[], edge_value=edge_value, val=val, split_type=split_type,
split_cond=split_cond)
self.model.append(node)
# also add it as a child of the parent node
if parent_id is not None:
self.model[parent_id].append_child(node_id)
return node_id
def __id3(self, attrs, records, parent_id=None, value=None):
"""
Function ID3 that returns a decision tree.
:param attrs: Set of attributes
:param records: Training set (list of record ids)
:param parent_id: ID of parent node
:param value: Value corresponding to the parent attribute, i.e., label of the edge on which we arrived to this node
:return:
"""
# empty training set or empty set of attributes => create leaf node with default class
if not records or not attrs:
self.__add_node(parent_id, node_type=NodeType.leaf, edge_value=value, val=self.default_class)
return
# if all records have the same target value => create leaf node with that target value
same = all(self.data[idx][IDX_TARGET] == self.data[records[0]][IDX_TARGET] for idx in records)
if same:
target = self.data[records[0]][IDX_TARGET]
self.__add_node(parent_id, node_type=NodeType.leaf, edge_value=value, val=target)
return
# find the attribute with the largest gain
splitting = self.__find_best_attr(attrs, records)
# add node
node_id = self.__add_node(parent_id, edge_value=value, val=splitting.attr, split_type=splitting.split_type,
split_cond=splitting.cond)
# TODO call tree construction recursively for each split
node = self.model[node_id]
for n_id in node.children:
self.__id3(attrs, records, node_id, node.val)
return self.model
def print_model(self, node_id=0, level=0):
node = self.model[node_id]
indent = " " * level
if node.type == NodeType.leaf:
print(indent + str(node.edge_value) + " [Leaf node] class=" + node.val)
else:
cond = " <= " + str(node.split_cond) if ATTR[node.val].type == AttrType.num else " == ? "
if node.type == NodeType.root:
print("[Root node] '" + ATTR[node.val].label + "'" + cond)
else:
print(indent + str(node.edge_value) + " [Internal node] '" + ATTR[node.val].label + "'" + cond)
# print tree for child notes recursively
for n_id in node.children:
self.print_model(n_id, level + 1)
def build_model(self):
self.__load_data()
#print(list(range(len(self.data))))
#print(list(range(len(self.data))))
self.model = [] # holds the decision tree model, represented as a list of nodes
# Get majority class
# Note: Counter returns a dictionary, most_common(x) returns a list with the x most common elements as
# (key, count) tuples; we need to take the first element of the list and the first element of the tuple
self.default_class = Counter([x[IDX_TARGET] for x in self.data]).most_common(1)[0][0]
self.__id3(set(range(len(ATTR) - 1)), list(range(len(self.data))))
def apply_model(self, record):
node = self.model[0]
while node.type != NodeType.leaf:
# TODO based on the value of the record's attribute that is tested in `node`,
# set `node` to one of its child nodes until a leaf node is reached
for n_id in node.children:
node = self.model[n_id]
return node.val
def main():
dt = DT()
print("Build model:")
dt.build_model()
dt.print_model()
print("\nApply model:")
print(dt.apply_model(['sunny', 85, 85, 'false']))
print(dt.apply_model(['overcast', 75, 85, 'true']))
print(dt.apply_model(['rain', 75, 85, 'false']))
if __name__ == "__main__":
Yeah you are right, records is a list of indexes to records, but I treated records as it was the value of the indexes. I made som changes to the function and it works now:
def __entropy(self, records): n = Counter([self.data[x][4] for x in records]) return sum([(-freq / len(records)) * math.log(freq / len(records), 2) for freq in n.values()])#eksempel:

Python - Passing Function Arguments

I am struggling on how to work out how I pass arguments from a function so that I can populate a list in another function - my code is:
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
#find the nearest neighbour to a particular node
def nearestNeighbour(currentNode, theNetwork):
nearestNeighbour = []
nodeIndex = 0
for node in nodeTable:
if node != 0 and currentNode.visited == false:
nearestNeighbour.append(nodeIndex)
nodeIndex +=1
return nearestNeighbour
currentNode = startNode
if __name__ == "__main__":
nodeTable = populateNodeTable()
theNetwork = network()
nearestNeighbour(currentNode, theNetwork)
So, I am trying to fill the nearestNeighbour list in my nearestNeighbour function with a list of nodes nearest to the other nodes. Now, the all the other functions work correctly, with all argument passing functioning as it should.
However, my nearestNeighbour function throws up this error message:
if node != 0 and
theNetwork[currentNode].visited ==
false: AttributeError: 'list' object
has no attribute 'visited'
(Apologies for the layout, haven't quite fathomed the use of the code quotes yet)
class Node(object):
def __init__(self, me, dists):
super(Node,self).__init__()
self.me = me
self.dists = dists
_inf = Network.INF
self.neighbors = sorted((i for i,dist in enumerate(self.dists) if i!=me and dist!=_inf), key=dists.__getitem__)
self.clear()
def clear(self):
self.dist = None
self.prev = None
def nearestNeighbor(self):
try:
return self.neighbors[0]
except IndexError:
return None
def __str__(self):
return "{0}: {1}".format(self.me, self.dists)
class Network(object):
INF = 10**6
#classmethod
def fromFile(cls, fname, delim=None):
with open(fname) as inf:
return cls([[int(dist) for dist in line.split(delim)] for line in inf])
def __init__(self, distArray):
super(Network,self).__init__()
self.nodes = [Node(me,dists) for me,dists in enumerate(distArray)]
def __str__(self):
return '\n'.join(self.nodes)
def floodFill(self, fromNode):
_nodes = self.nodes
for n in _nodes:
n.clear()
_nodes[fromNode].dist = 0
# left as an exercise ;-)
def distances(self):
return [n.dist for n in self.nodes]
def main():
nw = Network.fromFile('network.txt', delim=',')
print(nw)
nw.floodFill(fromNode=0)
print(nw.distances())
if __name__=="__main__":
main()
That's because theNetwork[currentNode] returns a list. In other words: theNetwork is a list of lists.
This is the line where it is done:
theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
theNetwork is a list of lists. A list (theNetwork[currentNode]) doesn't have a visited attribute.
Perhaps you intended something like:
for line in f.readlines():
theNetwork.extend((int(node) for node in line.split(',')))

Categories