instantiating an object with a dictionary field prints empty - python

In the following code, I'm trying to print a dictionary that contains the node gateway id as well as the node id as {1:gatewayid, 2:deviceNodeId}, however when instantiating the gateways and the nodes with the dictionary field, it prints an empty dictionary. I'll greatly appreciate your help please:
class Node():
def __init__(self,id, gatewayIds):
self.id=id
self.gatewayIds={}
class LevelNNode(Node):
def __init__(self, id, gatewayIds):
super(LevelNNode,self).__init__(id, gatewayIds)
self.balance=0
totalLevels=2
Dn = 10
Gn = 2
NODES = []
GATEWAYIDS = [chr(x+97) for x in range(Gn)]
if totalLevels==2:
for i in GATEWAYIDS: # Create all the gateways
otherGatewayIds = GATEWAYIDS.copy()
otherGatewayIds.remove(i)
NODES.append(LevelNNode(i, {1:i}))
deviceNodeId = 1 # Create the nodes for the level below
for i in GATEWAYIDS:
for j in range(Dn):
NODES.append(Node(deviceNodeId, {1:i, 2:deviceNodeId}))
deviceNodeId += 1
for x in NODES:
print (x.id, x.gatewayIds)

That's because you set the instance variable equal to {} and don't actually use the parameter you pass in. In the Node's __init__ try this: self.gatewayIds=gatewayIds

Related

Graph of objects using graph-tool

I'm trying to use the library graph-tool to create a new graph of objects. In particular I want some nodes of students and others of professors.
In the following the code I've written, I'm not able to add the vertices of students/professors.
The documentations https://graph-tool.skewed.de/static/doc/quickstart.html#property-maps explains that I have to use the class PropertyMap, it's quite weird for me...
Could someone explain to me how to use it? Thanks.
This is my code:
from graph_tool.all import *
class Student:
def __init__(self, name):
self.name = name
class Professor:
def __init__(self, name):
self.name = name
g = Graph()
s = Student("Luke")
p = Professor("Adam")
print(s.name)
print(p.name)
Well first you need to add the vertices to the graph
# your code
# from graph_tool.all import * # avoid importing all, it makes it inclear what you are using afterwards
import graph_tool as gt
class Student:
def __init__(self, name):
self.name = name
class Professor:
def __init__(self, name):
self.name = name
g = gt.Graph()
s = Student("Luke")
p = Professor("Adam")
print(s.name)
print(p.name)
Luke
Adam
you create a property map with for the type of your users
g.vertex_properties['user_type'] = g.new_vertex_property('string')
This will be a property for your nodes. You can create how many you want and then set their user_type
For exemple :
# creating a graph of 3 users
g.add_vertex(3)
# Let's set the first vertex as a professor
g.vp['user_type'][g.vertex(0)] = 'professor'
# and the subsequent as students
for v in g.get_vertices()[1:]:
g.vp['user_type'][v] = 'student'
# let's add an edge from the professor to the first student
g.add_edge(g.vertex(0), g.vertex(1))
<Edge object with source '0' and target '1' at 0x7f2c30370c30>
Now you can draw your graph using the property
def translate_elts_to_gtshape(g, source_prop='user_type', tdict=None):
"""This function adds a new property map called 'shape' to graph g. It is populated by translating the source_prop with the tdict (translation dictionary) which should map source_property entries to shapes"""
if tdict is None:
tdict = {'professor': 'square',
'student': 'circle'}
# source_property map array. It's of string type so we use get_2d_array
svp = g.vp[source_prop].get_2d_array([0])[0]
for k, v in tdict.items():
# for each key, value pair of tdict we change the source value (ie k) to the shape (v)
svp[svp == k] = v
# and now we create the new property shape
g.vertex_properties['shape'] = g.new_vertex_property('string')
for v, p in zip(g.vertices(), svp):
# and copy in it the shape
g.vp['shape'][v] = p
# we return the new property created, although it is already added to the graph as an internal property
return g.vp['shape']
translate_elts_to_gtshape(g)
<PropertyMap object with key type 'Vertex' and value type 'string', for Graph 0x7f2c5c3d6510, at 0x7f2c2997c950>
# let's just check what we have in our newly created shape property
[g.vp['shape'][v] for v in g.vertices()]
['square', 'circle', 'circle']
# and now let's use it to draw our graph
import graph_tool.draw as gtd
pos = gtd.sfdp_layout(g)
gtd.graph_draw(g, pos=pos,
output_size = (300, 300),
output_file = 'mynetwork.png', # where your file goes
vertex_shape=g.vp['shape'],
vertex_text=g.vertex_index)
<PropertyMap object with key type 'Vertex' and value type 'vector<double>', for Graph 0x7f2c5c3d6510, at 0x7f2c14291590>

dynamic instances of a class object overwriting each other

I have a simple class that stores simple data. The class is as follows.
class DataFormater:
def __init__(self, N, P, K, price):
self.N = N
self.P = P
self.K = K
self.price = price
The code that calls this class is
from DataFormater import DataFormater
#global variables
ObjectList = [0,1,2,3,4,5,6,7,8,9,10,
11,12,13,14,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50]
ObjectListCounter = 0
# main
print "enter you N-P-K values, followed by a coma, then the price"
print "example ----> 5 5 5 %50 "
print "return as many values as you want to sort, then enter, 'done!' when done."
while True:
RawData = raw_input()
if RawData == 'done!':
break
else:
ObjectList[ObjectListCounter] = DataFormater
ObjectList[ObjectListCounter].N = int(RawData[0])
# very simple test way of putting first indice in ObjectList[ObjectListCounter].N
ObjectListCounter += 1
print ObjectList[0].N
print ObjectList[1].N
My idea is that ObjectList[0] would create that object '1' that I could call with 1.N
But, when I call these, it seems that I have overwritten the previous instances.
this is what prints...
return as many values as you want to sort, then enter, 'done!' when done.
12
1
done!
1
1
Thanks so much! And I know that my post is messy, I don't exactly know how to make it more "pretty"
So, it looks like you are assigning the actual class (instead of an instance of the class) in your loop. Where you do this:
ObjectList[ObjectListCounter] = DataFormater
I think what you actually want is this
ObjectList[ObjectListCounter] = DataFormater(...insert args here....)
EDIT to address the comments:
Your class init method looks like this:
def __init__(self, N, P, K, price):
That means that to create an instance of your class, it would look like this:
my_formater = DataFormater(1, 2, 3, 4)
You would then be able to access my_formater.N which would have a value of 1.
What you are trying to do instead is access a CLASS level attribute, DataFormater.N. This is generally used in situations where you have a constant variable that does not change between instances of the class. For example:
class DataFormater():
CONSTANT_THING = 'my thing that is always the same for every instance'
You would then be able to access that variable directly from the class, like this:
DataFormater.CONSTANT_THING
I hope that clears things up.

Weird thing in python classes ?

I was trying to implement a shortest path algorithm in python. I ran into some trouble when I attempted to connect my points on the path.
I have a class called NODE
I made an array of these nodes and then created new nodes in them like this:
nodes = []
for r in range ( 0, 3 ):
for c in range ( 0, 3 ):
nodes.append( NODE( c*WIDTH/20 + 30, r*HEIGHT/20 + 30, 10 ) )
This created nodes, which is fine, I can draw them just fine.
At first I attempted connecting them by adding a list of node objects into the the NODE class. I ran into some issues, I thought the problem is with the recursive classes, so to test I did this. Where connections is a blank array within the NODE class.
nodes[0].connections.append( 0 )
print nodes[0].connections
nodes[1].connections.append( 1 )
print nodes[1].connections
print nodes[0].connections
This is where I found the problem, Maybe I'm just being stupid, or It's a language thing ? Dunno, but I thought I'd ask.
The output is this:
[ 0 ]
[ 0, 1 ]
[ 0, 1 ]
As you can see, I only added 1 object to the connections list in the index 1. However when I print the contents, I see two.... And this confuses me.
Possibilty 1: your code looks like this:
class NODE:
connections = []
def __init__(self, value):
self.value = value
nodes = [NODE(23), NODE(42)]
nodes[0].connections.append( 0 )
print nodes[0].connections
nodes[1].connections.append( 1 )
print nodes[1].connections
print nodes[0].connections
Solution: class instance attributes should be defined inside __init__. If you define connections at the class level, then every single instance of NODE will share the same one connections list.
class NODE:
def __init__(self, value):
self.value = value
self.connections = []
Possibility 2: your code looks like this:
class NODE:
def __init__(self, value, connections = []):
self.value = value
self.connections = connections
nodes = [NODE(23), NODE(42)]
nodes[0].connections.append( 0 )
print nodes[0].connections
nodes[1].connections.append( 1 )
print nodes[1].connections
print nodes[0].connections
Solution: the default value in an argument list is created only once, so all instances of NODE using that default value will share the same one list. use a non-mutable sentinel value to indicate that no argument was passed. None is usually suitable for this task.
class NODE:
def __init__(self, value, connections = None):
self.value = value
if connections is not None:
self.connections = connections
else:
self.connections = []

My recursive function (populates a tree structure) is adding to the root node during every loop/call

I have an algorithm to populate a tree like structure (class: Scan_instance_tree), but unfortunately, during each call, it is incorrectly adding to the root node's children, as well as to the new child nodes created further down in the tree.
As a clue, I saw another thread...
Persistent objects in recursive python functions
...where this problem was mentioned briefly, and it was suggested that the parameters passed had to be mutable. Is that the answer, and how would I do this, in this example???
Here is my current code:
class Field_node(object):
field_phenotype_id = -1
field_name = ''
field_parent_id = -1
child_nodes = []
class Scan_instance_tree(object):
root_node = None
def __init__(self, a_db):
self.root_node = Field_node()
scan_field_values = self.create_scan_field_values(a_db) # This just creates a temporary user-friendly version of a database table
self.build_tree(scan_field_values)
def build_tree(self, a_scan_field_values):
self.root_node.field_name = 'ROOT'
self.add_child_nodes(a_scan_field_values, self.root_node)
def add_child_nodes(self, a_scan_field_values, a_parent_node):
i = 0
while i < len(a_scan_field_values):
if a_scan_field_values[i]['field_parent_dependancy'] == a_parent_node.field_phenotype_id:
#highest_level_children.append(a_scan_field_values.pop(a_scan_field_values.index(scan_field)))
child_node = Field_node()
child_node.field_phenotype_id = a_scan_field_values[i]['field_phenotype_id']
child_node.field_name = a_scan_field_values[i]['field_name']
child_node.field_parent_dependancy = a_scan_field_values[i]['field_parent_dependancy']
a_parent_node.child_nodes.append(child_node)
a_scan_field_values.remove(a_scan_field_values[i])
# RECURSION: get the child nodes
self.add_child_nodes(a_scan_field_values, child_node)
else:
i = i+1
If I remove the recursive call to self.add_child_nodes(...), the root's children are added correctly, ie they only consist of those nodes where the field_parent_dependancy = -1
If I allow the recursive call, the root's children contain all the nodes, regardless of the field_parent_dependancy value.
Best regards
Ann
When you define your Field_node class, the line
child_nodes = []
is actually instantiating a single list as a class attribute, rather than an instance attribute, that will be shared by all instances of the class.
What you should do instead is create instance attributes in __init__, e.g.:
class Field_node(object):
def __init__(self):
self.field_phenotype_id = -1
self.field_name = ''
self.field_parent_id = -1
self.child_nodes = []

Creating several classes in Python dynamically

I will appreciate any effort to clarify the following: is there a way in Python to dynamically create one object per class, where several classes are declared? My silly guess can be described as following:
...
suppose we have some data from db
props = dict_cur.fetchall()
classes_names = []
data = []
for i in props:
classes_names.append(i['client_name'].title())
classes = []
data = []
for i in props:
data.append(dict(i))
for i, d in zip(classes_names, data):
classes.append(type(i, (object,), dict(**d)))
print classes
#printing list of classes
objects = []
for obj in classes:
objects.append(obj())
for obj in objects:
print obj.client_name, obj.client_id
This is very naive approach and it never lets inherit from created classes in a regular way, just like this:
class ClientProcess(Someclient): #Someclient is the name of the created class before
def __init__(self):
print "Someclient stuff"
The goal is pretty simple: create the objects of several classes, preferably with the properties that are stored in the tables, but at the same time have class declaration for every client which will have specific method implemented that will very from class to class. The initial script that works well and uses Python version of Factory method is not sufficient because it only can process one class(client) a time (based on command-line argument which is client id).
If I understand you correctly, you can use the following ways to subclass dynamically created classes:
In : classes = []
In : cls_name = 'BaseCls1'
In : classes.append(type(cls_name, (object, ), {'x': 1}))
In : classes[0].x
Out: 1
In : classes[0].__bases__
Out: (object,)
# two ways to create subclass out of BaseCls1
In : class SubCls1(classes[0]):
: x = 2
:
In : SubCls1.x
Out: 2
In : SubCls1.__bases__
Out: (__main__.BaseCls1,)
In : SubCls2 = type('SubCls2', (classes[0],), {'x': 2})
In : SubCls2.x
Out: 2
In : SubCls2.__bases__
Out: (__main__.BaseCls1,)
class GetConfig(object):
def __init__(self, client_id):
self.client_id = client_id
#construct the query here to get the clients data ...where client_id = self.client_id
d = {'logfile': 'some_long_path', 'contact_name': 'some_name'}
class FirstClient(object):
def __init__(self):
client_id = '111111111'
props = GetConfig(client_id)
#print props.d
def check_source(self):
print "Checking FirstClient source"
return "Something"
#print props.d
def check_downl(self):
print "Checking FirstClient downloaded"
class SecondClient(object):
def __init__(self):
client_id = "222222"
props = GetConfig(client_id)
def check_source(self):
print "Checking SecondClient source"
def check_downl(self):
print "Checking SecondClient downloaded"
myfactory = {
"firstclient" : FirstClient,
"secondclient" : SecondClient,
}
for i in myfactory.values():
i().check_source()
i().check_downl()
collections.namedtuple. done.
Edit: to elaborate,
from collections import namedtuple
rows = dict_cur.fetchall()
# creates the class Row which is a tuple, but each position argument
# corresponds to the column name in that position
# Row can be instantiated as a tuple and then its elements can be accessed
# by name class attributes
Row = namedtuple("Row", zip(*dict_cur.description)[0])
objects = [Row(row) for row in rows]
for o in objects:
print o.client_name, ' is ' , o

Categories