Instead of using a dict to store and pass data we are going completely OOPS approach of storing the data as class attributes and call the get methods defined according to need.
In Java i was able to achieve this but having some trouble in Python. Any Solution would be helpful.
import json
class InputModel:
def __init__(self, input_payload):
self.id1 = input_payload["id1"]
self.route = RouteModel(input_payload["route"])
self.id2 = input_payload["id2"]
self.id3 = input_payload["id3"]
self.id4 = input_payload["id4"]
self.id5 = input_payload["id5"]
def get_id1(self):
return self.id1
#similar for other ids
class RouteModel:
def __init__(self, input_payload_route):
self.id6 = input_payload_route["id6"]
self.id7 = input_payload_route["id7"]
def get_id6(self):
return self.id6
#similar for other ids
json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
im = InputModel(json_dict)
print(im.get_id1())
print(im.get_id6())
not able to access the nested class attributes
Seems like you went for 1 extra indent in your class methods, thus you couldn't reach them.
Also, to reach id6 of RouteModel, you had to refer to 'route' first:
import json
class InputModel:
def __init__(self, input_payload):
self.id1 = input_payload["id1"]
self.route = RouteModel(input_payload["route"])
self.id2 = input_payload["id2"]
self.id3 = input_payload["id3"]
self.id4 = input_payload["id4"]
self.id5 = input_payload["id5"]
def get_id1(self):
return self.id1
#similar for other ids
class RouteModel:
def __init__(self, input_payload_route):
self.id6 = input_payload_route["id6"]
self.id7 = input_payload_route["id7"]
def get_id6(self):
return self.id6
#similar for other ids
json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
im = InputModel(json_dict)
print(im.get_id1())
print(im.route.get_id6())
Output:
string
string
The problem is that you are only defining get_id* in your local scope, you need to assign it to the instance if you insist on defining it inside the __init__ method.
I minimized your code example to isolate your issue.
class RouteModel:
def __init__(self):
self.id6 = "foo"
def get_id6(self_=self):
return self_.id6
self.get_id6 = get_id6
rm = RouteModel()
print(rm.get_id6())
>>> "foo"
If I understand your question correctly, you want to be able to access the ids directly as attributes, no matter how deep they are nested in the dictionary.
This solution creates the attributes recursively:
import json
class InputModel:
def __init__(self, payload):
self.create_attrs(payload)
def create_attrs(self, d):
for key, value in d.items():
# if the value is a dict, call create_attrs recursively
if isinstance(value, dict):
self.create_attrs(value)
else:
# create an attribute key=value, e.g. id1="string"
setattr(self, key, value)
json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
im = InputModel(json_dict)
print(im.id1)
print(im.id6)
After going through answers provided, mostly have defined instance attributes and not class attributes.
Correct me if I'm wrong here but I think this is how class attributes are defined right?
import json
class InputModel:
def __init__(self, input_payload):
InputModel.id1 = input_payload["id1"]
InputModel.route = RouteModel(input_payload["route"])
InputModel.id2 = input_payload["id2"]
InputModel.id3 = input_payload["id3"]
InputModel.id4 = input_payload["id4"]
InputModel.id5 = input_payload["id5"]
def get_id1():
return InputModel.id1
#OR
##classmethod
#def get_id1(cls):
# return cls.id1
#similar for other ids
class RouteModel:
def __init__(self, input_payload_route):
RouteModel.id6 = input_payload_route["id6"]
RouteModel.id7 = input_payload_route["id7"]
def get_id6():
return RouteModel.id6
#similar for other ids
json_str = '{"id1":"string","route":{"id6":"string","id7":"string"},"id2": "string","id3": "string","id4": "string","id5": "string"}'
json_dict = json.loads(json_str)
InputModel(json_dict)
print(InputModel.get_id1())
print(InputModel.route.get_id6())
print(RouteModel.get_id6())
Related
I need to have 100 of those similar python scripts that have MyData class from MyData_1 to MyData_100.
import torch
import numpy as np
from torch_geometric.data import InMemoryDataset, Data
from torch_geometric.utils import to_undirected
class MyData_1(InMemoryDataset):
def __init__(self, root, transform=None):
super(MyData_1, self).__init__(root, transform)
self.data, self.slices = torch.load(self.processed_paths[0])
#property
def raw_file_names(self):
return "mydata_1.npz"
#property
def processed_file_names(self):
return "data_1.pt"
def process(self):
raw_data = np.load(self.raw_paths[0])
cluster_data = torch.load('./raw/total_clusters.pt')
x = torch.from_numpy(raw_data['x'])
y = torch.from_numpy(raw_data['y'])
pos = torch.stack([x,y], dim=-1)
cp = torch.from_numpy(raw_data['cp'])
data_list = []
for i in range(cp.size(0)):
data = Data(x=cp[i].view(-1,1),pos=pos.view(-1,2), cluster=cluster_data[0])
data_list.append(data)
torch.save(self.collate(data_list), self.processed_paths[0])
I'm trying to do this because each MyData class calls different mydata_1,2,...100.npz to generate dataset.
Is there any way to make this fast?
Thanks in advance!
I didn't fully understand the reason why you need to create 100 different classes.
Is it because you need to return mydata_1.npz to mydata_100.npz? If then, You can create a single class like this:
class Myclass:
def __init__(self, index):
self.index = index
def raw_file_names(self):
return "mydata_{}.npz".format(self.index)
Then, at another script like main.py, you can create/assign it like:
for i in range(100):
exec('dataset_{} = MyData_{}({})'.format(i, i, i))
I believe you can build your own code that fits your problem with above examples.
You can achieve this by creating Metaclass(subclass ) below is a example how to pass dynamic name of class in subclass magicfunction
MyDynamicSubclass
class MyClass:
def __init_subclass__(cls, my_name):
print(f"Subclass created and my name is {my_name}")
print(cls, cls.__class__.__name__)
MyDynamicSubclass = type("MyDynamicSubclass", (MyClass,), {}, my_name="Ellis")
output:
<class 'main.MyDynamicSubclass'> type
I am trying to call the sum_method function from my evaluation class to my main one, however I run into many errors. I want to use the new_data as the data parameter of my sum_method function.
evaluation class:
class evaluation():
def __init__(self, data):
self.data = data
def sum_method(self):
montant_init = self.data.loc[self.data['Initiateur'] == 'Glovoapp', 'Montant (centimes)'].sum()
print(montant_init)
main class:
class main(evaluation):
new_data.to_csv("transactions.csv", index=False)
self.data = new_data
def call_sum(self, new_data):
init_eval = evaluation.sum_method(self=new_data)
print(init_eval)
init_evalobj = main()
init_evalobj.call_sum()
if you use the method in your inherence class just use self
so:
init_eval = self.sum_method()
the self argument is passed in python automaticly as first parameter
update
you also should return a value:
def sum_method(self):
montant_init = self.data.loc[self.data['Initiateur'] == 'Glovoapp', 'Montant (centimes)'].sum()
print(montant_init)
return montant_init
I'd suggest making some changes to the both classes, to encapsulate the .data member variable in the base class. My preference would also be to separate out the calculation from the display, so leave all the print statements in the call_sum() function.
class evaluation:
def __init__(self, data):
self.data = data
def sum_method(self):
montant_init = self.data.loc[self.data['Initiateur'] == 'Glovoapp', 'Montant (centimes)'].sum()
return montant_init
class main(evaluation):
def __init__(self):
# Reduce csv content to what's needed for analysis
data_csv = pd.read_csv('transactions.csv')
# --> removing unnecessary data
new_data = data_csv[['Opération', 'Initiateur', 'Montant (centimes)', 'Monnaie',
'Date', 'Résultat', 'Compte marchand', 'Adresse IP Acheteur', 'Marque de carte']]
# --> saving changes...
new_data.to_csv("transactions.csv", index=False)
super().__init__(new_data) //Initialize the base class
def call_sum(self):
print('Glovoapp "montant" generated')
init_eval = self.sum_method() //Call the method from the base class
print(init_eval)
I looked at this example and tried to write a class which holds the header information.
From another class, I would call this class and get the dictionary to use.
# -*- coding: utf-8 -*-
import binascii
import codecs
from datetime import datetime
from collections import defaultdict
class HeaderInfo(dict, object):
def __init__(self):
header_dict = defaultdict(list) # This shall hold all the issues in the parsed file
# super(HeaderInfo, self).__init__(file)
self._object = "C:\Sample.log"
file = open(self._object, "rb")
self._dict = {}
byte = file.read(4)
logFileSize = int.from_bytes(byte, "little")
header_dict = self.add('logFileSize', logFileSize)
dict = self.add('logFileSize', logFileSize)
# print((dict))
byte = file.read(20)
hexadecimal = binascii.hexlify(byte)
header_dict = self.add('fileType', codecs.decode(hexadecimal, "hex").decode('ascii'))
dict = self.add('fileType', codecs.decode(hexadecimal, "hex").decode('ascii'))
# print((dict))
byte = file.read(5)
hexadecimal = binascii.hexlify(byte)
header_dict = self.add('fileVersion', codecs.decode(hexadecimal, "hex").decode('ascii'))
dict = self.add('fileVersion', codecs.decode(hexadecimal, "hex").decode('ascii'))
# print((dict))
byte = file.read(10)
hexadecimal = binascii.hexlify(byte)
header_dict = self.add('fileNumber', codecs.decode(hexadecimal, "hex").decode('ascii'))
dict = self.add('fileNumber', codecs.decode(hexadecimal, "hex").decode('ascii'))
def add(self, id, val):
self._dict[id] = val
return self._dict
# print the data
hi = HeaderInfo()
print(hi)
when I tried with print statements,the data is printed, but
hi = HeaderInfo()
, doesn't return anyvalue in "hi".
any idea to return the dict value if HeaderInfo() is called?
hi is a variable pointing to an instance of your class HeaderInfo - it is not the internal dictionary self._dict of your class.
You essentially have a class thats a dict that also has a member that is a dict - you fill the member - not the class itself.
Printing hi won't show whats in your self._dict, unless you overwrite the def __str__(self) and maybe def __repl__(self) methods of your class to customize how your class is printed (by itself/inside lists).
To print the member, add
def Get_Data(self): # or some other name
return self._dict
to your class and use
print(hi.Get_Data())
to view whats inside your members dictionary.
If you want to store stuff in you class itself, change your add method
def add(self, id, val):
self[id] = val # store it inside yourself, not your member
return self # this is questionalbe - as is the whole method
# if you do not want to make it part of your public api
I have a class which is pulling JSON data with keys, but the problem is that per instance of this class, the JSON data may not have keys for everything I am trying to grab. Currently, my class is set up like this:
class Show():
def __init__(self, data):
self.data = data
self.status = self.data['status']
self.rating = self.data['rating']
self.genres = self.data['genres']
self.weight = self.data['weight']
self.updated = self.data['updated']
self.name = self.data['name']
self.language = self.data['language']
self.schedule = self.data['schedule']
self.url = self.data['url']
self.image = self.data['image']
And so on, there are more parameters than that. I'm trying to avoid the messiness of having a try-except block for EACH AND EVERY one of those (27) lines. Is there a better way? Ultimately, I want a parameter to be assigned None if the JSON key doesn't exist.
If you're going to set a default value to the attribute if it's not in the data dictionary, use data.get('key') rather than data['key']. The get method will return None if the key does not exist, rather than raising a KeyError exception. If you want a different default value than None, you can pass a second argument to get and that is what will be returned.
So, your code could become:
class Show():
def __init__(self, data):
self.data = data
self.status = self.data.get('status')
self.rating = self.data.get('rating')
self.genres = self.data.get('genres')
self.weight = self.data.get('weight')
self.updated = self.data.get('updated')
self.name = self.data.get('name')
self.language = self.data.get('language')
self.schedule = self.data.get('schedule')
self.url = self.data.get('url')
self.image = self.data.get('image')
Use dict.get, which provides a default value instead of raising an exception for missing keys.
For example, you can change this:
self.status = self.data['status']
into this:
self.status = self.data.get('status')
You could change your code to something like:
class Show():
def __init__(self, data):
self.data = data
self.__dict__.update(data)
data = {'status': True, 'ratings': [1,2,3], 'foo': "blahblah"}
aShow = Show(data)
"""
>>> aShow.status
True
>>> aShow.ratings
[1,2,3]
>>> aShow.something_not_in_dict
AttributeError: Show instance has no attribute 'something_not_in_dict'
"""
Which does exactly the same, and trying to access something from your Show instance that isn't a key in your data dictionary would raise an AttributeError
I have this dictionary:
{"id":3,"name":"MySQL","description":"MySQL Database Server - Fedora 21 - medium","image":"","flavor":""}
And I have this object:
class Record():
id = None
name = None
description = None
image = None
flavor = None
How can I assign values from the dictionary to their corresponding class fields?
Take a dict object as the parameter of init function:
class Record(object):
def __init__(self,record_dict):
try:
self.id = record_dict['id']
self.name = record_dict['name']
self.description = record_dict['description']
self.image = record_dict['image']
self.flavor = record_dict['flavor']
except KeyError:
print 'KeyError'
def get_name(self):
return self.name
adict = {"id":3,"name":"MySQL","description":"MySQL Database Server - Fedora 21 - medium","image":"","flavor":""}
one_obj = Record(adict)
print one_obj
print one_obj.get_name()
output:
<__main__.Record object at 0x022E4C90>
MySQL
works for me...
You probably want something like this:
class Record:
def __init__(self, myDict):
self.id = myDict[“id”]
self.name = myDict[“name”]
self.description = myDict[“description”]
self.image = myDict[“image”]
self.flavor = myDict[“flavor”]
And call it:
rec = Record(myDict)
See here to understand the difference between class and instance variables.
Long story short, class variables have a single value for every instance of the class while instance variables values are unique to each instance.
A class variable is defined like this:
class myClass:
Classvar = ‘something’
An instance variable is defined like this:
class myClass:
def __init__():
Self.instanceVar = ‘something else’
This has already been answered here:
Convert Python dict to object?
My favorite method is this one: x.__dict__.update(d)
You can assign them as follows, assuming your dictionary name is input
id = input['id']
name = input['name']
description = input['description']
image = input['image']
flavor = input['flavor']
Try this method in which you grab the attributes of the object:
r = Record()
attributes = [i for i in dir(r) if not i.startswith('_')]
Basically, there are a bunch of background attributes that contain a bunch of underscores. The dir method gets all the attributes and we create a list of the ones that we want. At this point:
# attributes = ['count', 'description', 'flavor', 'id', 'image', 'index', 'name']
So now we use __setattr__ to set the attributes we just grabbed according to the my_dict
for i in attributes:
r.__setattr__(i, my_dict[i])
See the code run online here.
When you create the Record, pass in the dictionary. Then map the key to the value.
Another simple method, see the code here
r = Record()
for k, v in my_dict.items():
exec('r.' + k + '="' + str(v) + '"')