I have created the following objects in python
It creates an object of class arc and then creates another object network using the object arc
class Arc:
# Creates an object of class arc
def __init__(self, tailNode = 0, headNode = 0, lowerBound = 0, upperBound = 0, cost = 0):
self.tailNode = tailNode
self.headNode = headNode
self.lowerBound = lowerBound
self.upperBound = upperBound
self.cost = cost
def displayArc(self):
print("Tail Node : ", self.tailNode, "\nHead Node : ", self.headNode, "\nLower Bound : ", self.lowerBound, "\nUpper Bound ; ", self.upperBound, "\nCost : ", self.cost, "\n")
class Node:
# Create an object of class node
def __init__(self, nodeName = 0, distLabel = 0, preNode = 0):
self.nodeName = nodeName
self.distLabel = distLabel
self.preNode = preNode
class Network:
# Creates a network from given arcs
def __init__(self, fileName):
global arcNo
arcNo = 0
self.fileName = fileName
f = open(self.fileName)
x = f.readlines()
arcList = [ Arc() for i in range(len(x))]
for i in range(len(x)):
temp = x[i]
temp = temp.split("\n")
temp = ",".join(map(str, temp))
temp = temp.split(",")
arcList[i] = Arc(temp[0], temp[1], temp[2], temp[3], temp[4])
arcNo += 1
print(arcNo)
net = Network("arcList.txt")
print(type(net))
print(net[1])
When the print statement comes says
4
<class '__main__.Network'>
Traceback (most recent call last):
File "Dijkstra.py", line 54, in <module>
print(net[1])
TypeError: 'Network' object does not support indexing
How do I support indexing so that I can call the network object by its index ?
Assuming net[index] returns the arcList variable you can simply override your [] operator as such
class Network:
def __getitem__(self,index):
return arcList[index]
Printing a class needs a method as well. This might help you
How to print a class or objects of class using print()?
In order to support indexing, your Network class should have a __getitem__() method (http://docs.python.org/reference/datamodel.html#object.getitem).
Related
I'm trying to make a model where nodes connect to one and other using OOP. I'd like each node to store the names of its inputs and connections within lists and have these lists as attributes. The code seems to function perfectly outside of the "connect" function.
It creates desired Connection object, but it creates erroneous attributes for the destination node and origin nodes. The desired attributes are:
A.inputs = [],
A.outputs = [B]
B.inputs = [A]
B.outputs = [0]
But instead of that I get:
A.inputs = [A]
A.outputs = [B}
B.inputs = [A]
B.outputs = [B}
CONNECTIONS = []
NODES = []
class Zone:
def __init__(self, height, width):
self.height = height
self.width = width
class Node:
def __init__(self, name, initial_activation, activation_function = "linear", inputs = [], outputs = [], location = (0,0)):
global NODES
self.name = name
self.activation = initial_activation
self.activation_function = activation_function
self.inputs = inputs
self.outputs = outputs
self.location = location
NODES.append(self)
def __repr__(self):
return(f"Node {self.name}")
class Connection:
def __init__(self, origin, destination):
self.origin = origin.name
self.destination = destination.name
def __repr__(self):
return(f"Connection from {self.origin} to {self.destination}")
def connect(origin, destination):
new_connection = Connection(origin, destination)
origin.outputs.append(destination.name)
destination.inputs.append(origin.name)
global CONNECTIONS
CONNECTIONS.append(new_connection)
A = Node("A",0)
B = Node("B", 0, location = (100,100))
A.__dict__ # verify it is correct before hand
B.__dict__
test_connection = Connection(A,B)
test_connection.__dict__
connect(A,B) # create connection
A.__dict__ # show erroneous result
B.__dict__
CONNECTIONS
CONNECTIONS[0].__dict__ # verify connection object is correct
I have tried to debug using print statements, but to no avail. I believe the problem is found within lines 33 and 34 but I cannot see an error in those lines.
I see that Node class has mutable default arguments values for variables inputs and outputs.
In code, you don't pass values for this argument so A.input refers to same list as B.input.
print(id(A.inputs) == id(B.inputs))
will print True.
You need to get rid off mutable default argument, f.e doing this:
class Node:
def __init__(self, name, initial_activation, activation_function="linear",
inputs=None, outputs=None, location=(0, 0)):
# Some code
self.inputs = inputs or []
self.outputs = outputs or []
Hi I'm having a problem in this classes I created the parent class extracao_nia with the method aplica_extracao for having the similar part of the execution that I use in others class and the diferent part is in the transform method definined in the children class
but I'm having an issue that the variables that I defined as list() are Null variable when I execute the code:
AttributeError: 'NoneType' object has no attribute 'append'
class extracao_nia:
def __init__(self, d=1, h=1, m=15):
self._data_base = "database"
self.UM_DIA = datetime.timedelta(days=d)
self.UMA_HORA = datetime.timedelta(hours=h)
self.INTERVALO = datetime.timedelta(minutes=m)
#property
def data_base(self):
return self._data_base
def aplica_extracao(self, SQL):
fim_intervalo = self.inicio + self.INTERVALO#
pbar = self.cria_prog_bar(SQL)#
while (fim_intervalo <= self.FIM):#
self.connector.execute(SQL,(self.inicio.strftime('%Y-%m-%d %H:%M'),fim_intervalo.strftime('%Y-%m-%d %H:%M')))#
for log in self.connector:#
self.transforma(log)
self.inicio = fim_intervalo
fim_intervalo = self.inicio + self.INTERVALO
class usuarios_unicos(extracao_nia):
def __init__(self, d=1, h=1, m=15, file='nodes.json'):
self._data_base = "database"
self.UM_DIA = datetime.timedelta(days=d)
self.UMA_HORA = datetime.timedelta(hours=h)
self.INTERVALO = datetime.timedelta(minutes=m)
self.file = file
self.ids = list()
self.nodes = list()
self.list_cpf = list()
def transforma(self, log):
context = json.loads(log[0])['context']
output = json.loads(log[0])['output']
try:
nr_cpf = context['dadosDinamicos']['nrCpf']
conversation_id = context['conversation_id']
nodes_visited = output['output_watson']['nodes_visited']
i = self.ids.index(conversation_id)
atual = len(self.nodes[i])
novo = len(nodes_visited)
if novo > atual:
nodes[i] = nodes_visited
except KeyError:
pass
except ValueError:
self.ids.append(conversation_id)
self.nodes = self.nodes.append(nodes_visited)
self.list_cpf = self.list_cpf.append(nr_cpf)
list.append returns None since it is an in-place operation, so
self.nodes = self.nodes.append(nodes_visited)
will result in self.nodes being assigned None. Instead you can just use
self.nodes += nodes_visited
I wrote a Node class and created three objects, when I'm assigning a value of a variable in the 1st object, the same variable of 2nd object is getting updated, same for the third object. Here's the code,
class Node:
nodes_neighbour = []
nodes_neighbour_loc = []
def __init__(self,location):
self.location = location
def addNeighbours(self,neighbours):
i = 0
while(i < len(neighbours)):
self.nodes_neighbour.append(neighbours[i])
self.nodes_neighbour_loc.append(neighbours[i].location)
i = i + 1
def setCosts(self,g,f):
self.g = g
self.f = f
n1 = Node([10,10])
n2 = Node([50,10])
n3 = Node([90,10])
n1.addNeighbours([n2,n3])
print(n2.nodes_neighbour_loc)
and it's printing,
[[50, 10], [90, 10]]
What's the problem??
Thanks in advance :)
Your members nodes_neighbour and nodes_neighbour_loc are instances of the class and are shared. You probably wanted this:
class Node:
def __init__(self,location):
self.location = location
self.nodes_neighbour = []
self.nodes_neighbour_loc = []
I have the following code in main.py:
import json
from data import message # data.py
from definitions import * # definitions.py
waypoints=[]
stations=[]
genes = []
jsonObj = json.loads(message) # from data.py
for item in jsonObj:
location = Location(id=item["id"], name=item["name"], lat=item["lat"], lon=item["lon"])
if ("is-start" in item) or ("is-end" in item):
location.isWaypoint = True
if "is-start" in item:
start = location
else:
end = location
else:
genes.append(location)
if "is-waypoint" in item:
location.isWaypoint = True
waypoints.append(location)
else:
stations.append(location)
Then, I have the following code in definitions.py:
from haversine import haversine
start = None
end = None
distMatrix = {}
def distBtwn(loc1, loc2):
dist = 0
pair = frozenset((loc1.id, loc2.id))
if pair in distMatrix:
dist = distMatrix[pair]
else:
coords1 = (loc1.lat, loc2.lon)
coords2 = (loc2.lat, loc2.lon)
dist = haversine(coords1, coords2)
distMatrix[pair] = dist
return dist
class Location:
def __init__(self, id, name, lat, lon):
self.id = id
self.name = name
self.lat = lat
self.lon = lon
self.isWaypoint = False
def __repr__(self):
rep = ""
if self.isWaypoint:
rep += "Waypoint "
else:
rep += "Station "
rep += "%d: %s (%f, %f)" % (self.id, self.name, self.lat, self.lon)
return rep
class Fitness:
def __init__(self, route):
self.route = route
self.distance = 0.0
self.fitness = 0.0
def routeDistance(self):
if self.distance = 0.0:
global start
global end
print(start)
print(self.route[0])
print(self.route[-1])
print(end)
pathDistance = distBtwn(start, self.route[0]) + distBtwn(self.route[-1], end)
for i in range(len(self.route) - 1):
pathDistance += distBtwn(self.route[i], self.route[i + 1])
self.distance = pathDistance
return self.distance
I run main.py, then entered the following in the shell, which throws an error:
>>> start
Waypoint 0: startPoint (3.333333, 3.333333)
>>> end
Waypoint 2: endPoint (4.444444, 4.444444)
>>> route = [waypoints[0], stations[15], waypoints[1]]
>>> fitA = Fitness(route)
>>> fitA.routeDistance()
None
Waypoint 1: waypointA (1.111111, 1.111111)
Waypoint 3: waypointC (2.222222, 2.222222)
None
Traceback (most recent call last):
File "<pyshell#78>", line 1, in <module>
fitA.routeDistance()
File "definitions.py", line 54, in routeDistance
pathDistance = distBtwn(start, self.route[0]) + distBtwn(self.route[-1], end)
File "definitions.py", line 10, in distBtwn
pair = frozenset((loc1.id, loc2.id))
AttributeError: 'NoneType' object has no attribute 'id'
>>> start
Waypoint 0: startPoint (3.333333, 3.333333)
>>> end
Waypoint 2: endPoint (4.444444, 4.444444)
Based on the above, routeDistance() is using the original None values of start and end from initialisation, even though they've been declared as global variables. Yet when called from the shell, those two variables have already been updated correctly with Location objects assigned. What is going wrong here?
Global variables are scoped to a module.
For example, in foo.py:
def set_variable(to):
global variable
variable = to
variable = None
And bar.py:
import foo
def get_variable():
global variable # Unnecessary, but to avoid confusion
return variable
variable = 1
print(foo.variable) # None
foo.set_variable(2) # Sets `foo`'s global variable to `2`
print(get_variable()) # 1; `bar`'s global variable is still 1
print(foo.variable) # 2; `foo`'s global variable is now `2`
You need to set definitions.start and definitions.stop.
I have a class defined like so:
class GameState:
def __init__(self, state=None):
if state is None:
self.fps = 60
self.speed = 1
self.bounciness = 0.9
self.current_level = None
self.next_frame_time = 0
self.init_time = 0
self.real_time = 0
self.game_time = 0
self.game_events = []
self.real_events = []
else:
# THIS being the key line:
self.__dict__.update(**state)
Is there an interface I can define, such that this works (i.e. the ** operator works on my class):
>>> a = GameState()
>>> b = GameState(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: update() argument after ** must be a mapping, not GameState
Essentially, I want b to take on all of the attributes of a.
I didn't think it would work, but I tried defining __getitem__ without any luck.
EDIT: I want to avoid using b's __dict__, as I want to also be able to pass a dictionary as an argument, and potentially use ** on GameState objects elsewhere.
let GameState inherit from dict :
class GameState(dict)
and rewrite the __setattr function like this :
def __setattr__(self,name,value) :
self.__dict__[name] = value
self[name] = value
in order for **obj to work, you have to implement (or inherit) the __getitem__() and keys() methods.
def __getitem__(self, item):
return self.__dict__[item] # you maybe should return a copy
def keys(self):
return self.__dict__.keys() # you could filter those
you could do that by updating the b's dict with that of a when creating b. Try this out:
class GameState:
def __init__(self, state=None):
if state is None:
self.fps = 60
self.speed = 1
self.bounciness = 0.9
self.current_level = None
self.next_frame_time = 0
self.init_time = 0
self.real_time = 0
self.game_time = 0
self.game_events = []
self.real_events = []
else:
if type(state) is dict:
self.__dict__.update(**state)
else:
self.__dict__.update(**state.__dict__)
a = GameState()
b = GameState(a)
you might want to create a deepcopy of the dict because you have a list object as part of the attributes. This is safer as there is no sharing of objects.