How do I convert a composite class into a dictionary? - python-3.x

I have a class called Large, which contains an instance of Small.
class Small:
s: str
def __init__(self):
self.s = "I am Small"
class Large:
small: Small
details: str
def __init__(self):
self.small = Small()
self.details = "Details???"
when I call the class and try to look at its dictionary, it looks broken
large = Large()
print(large.__dict__)
{'small': <__main__.Small object at 0x1110e2e50>, 'details': 'Details???'}
how do I force the small attribute to a dictionary also?

You can do this like:
>>> class Small:
def __init__(self):
self.s = "I am Small"
>>> class Large:
def __init__(self):
self.small = Small()
self.details = "Details???"
>>> def object_to_dict(instance):
output = {}
if not isinstance(instance, dict):
items = instance.__dict__.items()
else:
items = instance.items()
for key,value in items:
if isinstance(value, Small):
output[key] = object_to_dict(value.__dict__)
else:
output[key] = value
return output
>>> large = Large()
>>> large.littleSmall = Small()
>>> print(object_to_dict(large))
{'small': {'s': 'I am Small'}, 'details': 'Details???', 'littleSmall': {'s': 'I am Small'}}
But it only get __dict__ for a Small object if there is more classes you should add them in isinstance() function as tuple on second argument

Related

Error trying to access a parent variable from his child class

So I have this class:
class UniversalHash(HashClass):
##################################################
def __init__(self):
super().__init__()
self.__MParamK = int(0)
self.__MParamC = int(0)
self.__MParamD = int(0)
# Override #
def FindHash(self, Key):
return (((self.__MParamK * Key) + self.__MParamC) % self.__MParamD) % self.__MParamL
def SetParamK(self, Value):
self.__MParamK = Value
def SetParamC(self, Value):
self.__MParamC = Value
def SetParamD(self, Value):
self.__MParamD = Value
And the parent class:
class HashClass:
##################################################
def __init__(self):
self.__MParamL = int(0)
def SetParamL(self, Value):
self.__MParamL = Value
def GetParamL(self):
return self.__MParamL
def FindHash(self, Key):
pass
When I try to access to the variable __MParamL (the variable created in the parent), it gives me an exception telling me that the variable is not an attribute of this class, I have searched on the web and it seems this is the correct way to write the code (maybe the overridden function is the problem?). Any help is appreciated
When you name an instance attribute with a leading double underscore, it will get name mangled, E.g.,
>>> class A:
... def __init__(self):
... self.x = 42
... self.__y = 42
...
>>> a = A()
>>> vars(a)
{'x': 42, '_A__y': 42}
Instead, you should just use a single underscore, E.g.,
>>> class A:
... def __init__(self):
... self.x = 42
... self._y = 42
...
>>> a = A()
>>> vars(a)
{'x': 42, '_y': 42}

Overload Parameter for Dict

this is my problem:
I have two classes. In the Student class, a dict is passed in the constructor. This dict contains a list of dict. How can I pass the elements from this list to the Course class?
The classes are updated with the dict.
The metaclass is for overloading the _update function which I use in the bouth classes. #singledispatchmethod is for this because I use two constructors. One for the data (individual parameters) and the others for the dict.
from functools import singledispatchmethod
class MetaObject(object):
def _update(self, newDict: dict):
for key, value in newDict.items():
setattr(self, key, value)
class Course(MetaObject):
_name: str
#singledispatchmethod
def __init__(self):
pass
#__init__.register
def _(self, name: str):
self._name = name
#__init__.register(dict)
def _(self, dict: dict):
self._update(dict)
def print(self):
print("name:", self._name)
class Student(MetaObject):
_name: str
_courses: list
#singledispatchmethod
def __init__(self):
pass
#__init__.register
def _(self, name: str, courses: list):
self._name = name
self._courses = courses
#__init__.register(dict)
def _(self, dictValue: dict):
self._update(dictValue)
def print(self):
print("Name:", self._name, "Couses:")
c: Course
for c in self._courses:
print(c)
course1 = Course("Data Structures")
course2 = Course("Computer Networks")
student = Student("Danish", [course1, course2])
std_info = {'_name': "Danish", '_courses': [{"_name": 'Data Structures'}, {"_name": 'Computer Networks'}]}
student = Student(std_info)
student.print()

PYTHON: How to access class object's members if the object is a key in a dictionary

I have the following class:
class car_class(object):
def __init__(self, mileage=11, tyre_size=11):
self.mileage = mileage
self.tyre_size = tyre_size
self.default_val = ''
def __hash__(self):
return hash((self.mileage, self.tyre_size))
def __getitem__(self, default_val):
return self.default_val
def __setitem__(self, default_val, mileage, tyre_size):
self[default_val] = str(mileage) + '_' + str(tyre_size)
def __eq__(self, other):
return (self.mileage, self.tyre_size) == (other.mileage, other.tyre_size)
def __str__(self):
return ('dict_cl: (tyre_size=\'%d\', mileage=\'%d\'' % (int(self.tyre_size), int(self.mileage)))
def __repr__(self):
return ('dict_cl: (tyre_size=\'%d\', mileage=\'%d\'' % (int(self.tyre_size), int(self.mileage)))
def __ne__(self, other):
# Not strictly necessary, but to avoid having both x==y and x!=y
# True at the same time
return not(self == other)
I also have a dictionary which takes the object of this class as the Key against a value as follows-
my_dict = dict()
dict_value_list = list()
mm_dict_cl = car_class()
mm_dict_cl.mileage = 29
mm_dict_cl.tyre_size = 265
dict_value_list.extend(['car_color'])
my_dict.update(mm_dict_cl = dict_value_list)
So the dictionary(my_dict)key has the class object(mm_dict_cl) as key and car_color as a value for this key. The Key is the class object itself having two attributes mileage and tyre_size.
Now when I print the following value of the dictionary I get the value as car_color as expected -
`>>>` print(my_dict[next(iter(my_dict))])
['car_color']
However I'm struggling to find a way to retrieve the properties of the class object.
>>>` print(next(iter(my_dict)))
mm_dict_cl
It prints the class name and the key type if printed as string.
`>>>` print(type(next(iter(my_dict))))
<type 'str'>
Query: How can then I access the object attributes of the key?
I want to check what is the value of tyre_size and mileage for a particular 'car_color' using the key of the dictionary my_dict
Please help, a novice here, trying to learn this language.
-edit: Fixed the extend call to the list for adding 'car_colour' as a list instead of a string as pointed by SorousH Bakhtiary.
The problem here is that you stored the name of the instance of your class as key in your dictionary("it is string"), so you have no control over the instance but because your object is defined in global namespace, you can retrieve it like this : (I simplified your class for the moment)
class car_class:
def __init__(self, mileage=11, tyre_size=11):
self.mileage = mileage
self.tyre_size = tyre_size
self.default_val = ''
my_dict = {}
dict_value_list = []
mm_dict_cl = car_class()
dict_value_list.append('car_color')
print(dict_value_list)
mm_dict_cl.mileage = 'temp1'
mm_dict_cl.tyre_size = 'temp2'
my_dict.update(mm_dict_cl=dict_value_list)
# here :
obj = globals().get(next(iter(my_dict)))
print(obj.mileage) # prints temp1
print(obj.tyre_size) # prints temp2
btw, you should have used append instead of extend method to add 'car_color'

Python: creating a dictionary: {int, class object} in a loop

I'd like to create a dictonary: {int, Class} in a loop, however the class object is being overriden.
I am pretty sure that this is a basic problem, but I am stuck
class Simple:
simpleDic = {
'name': {""},
'age': {1}}
def __init__(self, name, age):
self.simpleDic['name'] = name
self.simpleDic['age'] = age
def __str__(self):
return "{} {}\n".format(self.simpleDic['name'], self.simpleDic['age'])
def foo():
myDict = {}
for x in range(3):
myDict[x] = Simple('Name' + str(x), x)
print(('{}: {}\n'.format("Creating", myDict[x])))
for key in myDict:
print(('{}: {}\n'.format("Printing" + str(key), myDict[key])))
#### Main program here ####
foo()
The output is as follows:
You're problem is on the last print
You're printing myDict[x] when you should print myDict[key]
x contains the last value from the first iteration, so you're practically printing the same key all over
Following your question in this comments:
class Simple:
def __init__(self, name, age):
self.simpleDic = {"name": name, "age": age}
def __str__(self):
return "{} {}\n".format(self.simpleDic['name'], self.simpleDic['age'])
def __repr__(self):
return "{} {}\n".format(self.simpleDic['name'], self.simpleDic['age'])
def foo():
myDict = {}
for x in range(3):
myDict[x] = Simple('Name' + str(x), x)
print(('{}: {}\n'.format("Creating", myDict[x])))
print(myDict)

Can we skip explicit object creation in Python

When I do not crate object for CP class, the operations are not captured. I am referring to the code below, Can somebody help me understand why we need obj creation in this case
from abc import ABC, abstractmethod
class P(ABC):
def __init__(self):
super().__init__()
self._pre_map = {}
self._pre_order = []
def set_pre(self, tag_value):
index = len(self._pre_map)
print(index)
self._pre_map[index] = tag_value
self._pre_order.append(index)
def execute(self):
pass
class CP(P):
def __init__(self):
super().__init__()
def execute(self):
self.prnt()
def prnt(self):
print (self._pre_map)
print (self._pre_order)
#Working
print("\n++++++++ working")
obj = CP()
obj.set_pre("test string added")
obj.execute()
#Not Working
print("\n+++++++ not working")
CP().set_pre("test string added")
CP().execute()
It produces,
++++++++working
0
{0: 'test string added'}
[0]
+++++++not working
0
{}
[]
When you call the class the second time with CP.execute(), you have created a completely new instance of the CP class. It is not going to have the text string you specified.
If you actually wanted it to print the values like the working one you can make the functions return self after each call in the P class. If you did that you could do something like this.
from abc import ABC, abstractmethod
class P(ABC):
def __init__(self):
super().__init__()
self._pre_map = {}
self._pre_order = []
def set_pre(self, tag_value):
index = len(self._pre_map)
print(index)
self._pre_map[index] = tag_value
self._pre_order.append(index)
##need to return self here
return self
def execute(self):
pass
class CP(P):
def __init__(self):
super().__init__()
def execute(self):
self.prnt()
def prnt(self):
print (self._pre_map)
print (self._pre_order)
#Working
print("\n++++++++ working")
obj = CP()
obj.set_pre("test string added")
obj.execute()
#Not Working
print("\n+++++++ not working: but now working after returning self in the P class")
CP().set_pre("test string added").execute()
++++++++ working
0
{0: 'test string added'}
[0]
+++++++ not working: but now working after returning self in the P class
0
{0: 'test string added'}
[0]
This would print the result you want.
The reason for the difference is the fact that in the first one, you are creating an instance, and using that instance the whole way through, whereas in the second one, you are using two different instances of your class.
The two different instances cannot share their attributes, so you are unable to recall what happened. If you really don't want to use a dedicated variable, change your P class to look like this:
class P(ABC):
...
def set_pre(self, tag_value):
index = len(self._pre_map)
print(index)
self._pre_map[index] = tag_value
self._pre_order.append(index)
return self
...
And use CP().set_pre("test string added").execute()

Resources