Access name of python objects - python

I made a class to work with Heating wires:
class Heating_wire:
def __init__(self, ro, L,d,alpha):
self.ro = ro
self.L = L
self.d = d
self.alpha = alpha
self.RT = [1]
self.vector_T = [1]
def get_R20(self):
self.R_20 = self.ro*self.L/(np.pi*(self.d/2)**2)
def calcular_RT(self,vector_temp):
self.vector_T = vector_temp
self.RT = [self.R_20*(1 + temp*self.alpha) for temp in vector_temp ]
return self.RT
instantiate some objects:
kantal = Heating_wire(1.45,0.25,0.3,4e-5)
nicromo = Heating_wire(1.18,0.25,0.3,0.0004)
ferroniquel = Heating_wire(0.86,0.25,0.3,9.3e-4)
wires = [kantal,nicromo,ferroniquel]
And made a plot:
leg = []
vector_temp = np.linspace(20,1000,1000)
for wire in sorted(wires):
wire.get_R20()
wire.get_RT(vector_temp)
line, = plt.plot(wire.vector_T,wire.RT)
leg.append(line)
plt.legend(leg,sorted(wires))
The issue is that I'm not getting the right names in the legend but the reference to the objects:
If I add a name attribute
def __init__(self,name, ro, L,d,alpha):
self.name = name
I can append the names
leg = []
names= []
vector_temp = np.linspace(20,1000,1000)
for wire in sorted(wires):
wire.get_R20()
wire.get_RT(vector_temp)
line, = plt.plot(wire.vector_T,wire.RT)
leg.append(line)
names.append(wire.name)
plt.legend(leg,names,loc='best')
But I wonder if there is a simpler way t solve this using directly the names of the objects in the list of wires:
kantal = Heating_wire(1.45,0.25,0.3,4e-5)
nicromo = Heating_wire(1.18,0.25,0.3,0.0004)
ferroniquel = Heating_wire(0.86,0.25,0.3,9.3e-4)
wires = [kantal,nicromo,ferroniquel]

Just do it like this and there's no duplication:
wires = [
Heating_wire("kantal", 1.45,0.25,0.3,4e-5),
Heating_wire("nicromo", 1.18,0.25,0.3,0.0004),
Heating_wire("ferroniquel", 0.86,0.25,0.3,9.3e-4)
]
To answer your question, no, objects cannot access the names they were given.

Related

Error appending to objects' list attributes in python

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 []

Python - Parent method don't acess the value of variable children

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

Changing a variable in one object is updating same variable of same class's another object

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 = []

nested object in a class Python

I am obviously missing something fundamental here. Hopefully someone can put me right! TIA
I have an array of objects whose class contains instances of another object. But when I set a property for one of these then they all change.
class direction():
dest = -1
lock = ''
class room():
roomname = ''
desc = ''
n = direction()
s = direction()
w = direction()
e = direction()
item = ''
rooms = []
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms[0].roomname = 'outside'
rooms[0].desc = ''
rooms[0].n.dest = 4
rooms[0].item = ''
rooms[1].roomname = 'hall'
rooms[1].desc = 'The hallway has doors to the east and south'
rooms[1].n.dest = 2
rooms[1].item = ''
if I iterate through the n.dest properties in the rooms list then all are returned as 2
It is as if the direction objects in each object in the rooms list are all a single instance and setting one value in one of them sets it for all of them.
Your attributes are all declared at class level, not instance level, meaning that every instance of the class will share the same values. I think you want:
class Room():
def __init__(self):
self.roomname = ''
self.desc = ''
self.n = direction()
self.s = direction()
self.w = direction()
self.e = direction()
self.item = ''
You're missing constructors, and therefore missing instance variables
You're defining class variables, so each variable is the same between all instances
In each class, you have declared a bunch of class attributes. An assignment like rooms[0].roomname = 'outside' creates an instance attribute that shadows room.roomname. However, you never actually make any such assignment to rooms[0].n, so each assignment to something like rooms[0].n.dest is adding an instance attribute dest to the same instance of direction shared by each instance of room.
In your attempt to "simplify" your code, you've made it more complicated. Define __init__ to set your instance attributes; class attributes are not used as often.
class Direction:
def __init__(self, dest, lock=''):
self.dest = dest
self.lock = lock
class Room:
def __init__(self, roomname, desc, item=''):
self.roomname = roomname
self.desc = desc
self.n = direction()
self.s = direction()
self.w = direction()
self.e = direction()
self.item = item
rooms = []
r = Room('outside', '')
r.n.dest = 4
rooms.append(r)
r = Room('hall', 'The hallway has doors to the east and south')
r.n.dest = 2
rooms.append(r)

Add all variables of instances within class with the same name

I have a class named Robot, which creates a number of instances of the classes Segment and Pointmass. All these instances have a variable mass. How can I obtain the total mass of all the objects within the object with the same variable name mass?
What I do right now:
class Robot:
def __init__(self, massJoint1, massJoint2, massJoint3, massSlide, reachSlide, massArm, lengthArm):
self.joint1 = Pointmass(massJoint1)
self.joint2 = Pointmass(massJoint2)
self.joint3 = Pointmass(massJoint3)
self.slide = Slide(massSlide, reachSlide)
self.arm = Arm(massArm, lengthArm)
self.totalmass = self.joint1.mass + self.joint2.mass + self.joint3.mass + self.slide.mass + self.arm.mass
def printVars(self):
attrs = vars(self)
print(', \n'.join("%s: \t%s" % item for item in attrs.items()))
print()
class Pointmass:
def __init__(self, mass):
self.mass = mass
self.location = None
class Segment:
def __init__(self, mass):
self.mass = mass
self.start = None
self.end = None
In which
self.totalmass = self.joint1.mass + self.joint2.mass + self.joint3.mass + self.slide.mass + self.arm.mass
is a very long line, and is really inconvenient when the Robot gains more arms and joints... Is there a better way to obtain the total mass?
You shouldn't be storing the joints in separate attributes. Rather, store a simple joints list; then you can simply use sum with a generator expression.
self.totalmass = sum(j.mass for j in self.joints)

Categories