Dynamically created instances in python - python

I have definition of parent class "Parent". I have also defined child classes "child1", "child2". In child's some of the functions are overided some not. But the problem is that number of instances will be defined in .ini file. Question is how to dynamically create this instances. I have tried with "type" but it is not working. Below code with comments
`
class Parent:
def __init__(self, var_1):
self.var_1 = var_1
def method1(self):
print("method1")
def method2(self):
print('method2')
class child1(Parent):
def __init__(self, var_1, var2):
self.var2 = var2
super().init(var_1)
def method2(self):
print('method2_own_implementation')
class child2(Parent):
def __init__(self, var_1, var2):
super().__init__(var_1)
self.var2 = var2
def method1(self):
print("method1_own_implementation")
#4 below lines it is how it normally works
A = child1(2, 'XXX')
A.method2()
B = child2(3, 'sfsaf')
B.method1()
#list_nr define that 2 object of both types should be created, how to do it programmatically?
list_nr = ['child1', 'child1', 'child2', 'child2']
i tried with type, but not working as expected
list_classes = {'child1':child1, 'child2':child2}
created_instances = []
for index, type_obj in enumerate(list_nr):
A = type(('type_obj' + str(index)), (list_classes[type_obj],), {'var_1': 3, 'var2': 'xxx'})
created_instances.append(A)
print(created_instances[0].method1())
after executing this receiving error:
print(created_instances[0].method1()) TypeError: method1() missing 1 required positional argument: 'self'

Not sure if I fully understood your question, but I'm guessing you just want created_instances to contain instance of the classes listed in list_nr with the variable var_1 initialized to 3 and var2 initialized to XXX? If so you are overcomplicating it a bit here is a modified version of your code that does so.
class Parent:
def __init__(self, var_1):
self.var_1 = var_1
def method1(self):
print("method1")
def method2(self):
print('method2')
class child1(Parent):
def __init__(self, var_1, var2):
self.var2 = var2
super().__init__(var_1)
def method2(self):
print('method2_own_implementation')
class child2(Parent):
def __init__(self, var_1, var2):
super().__init__(var_1)
self.var2 = var2
def method1(self):
print("method1_own_implementation")
# 4 below lines it is how it normally works
A = child1(2, 'XXX')
A.method2()
B = child2(3, 'sfsaf')
B.method1()
# list_nr define that 2 object of both types should be created, how to do it programmatically?
list_nr = ['child1', 'child1', 'child2', 'child2']
list_classes = {'child1': child1, 'child2': child2}
created_instances = []
for index, type_obj in enumerate(list_nr):
A = list_classes[type_obj](var_1= 3, var2= 'xxx')
created_instances.append(A)
print(created_instances[0].method1())
The main change I've done is change this line
A = type(('type_obj' + str(index)), (list_classes[type_obj],), {'var_1': 3, 'var2': 'xxx'})
to
A = list_classes[type_obj](var_1= 3, var2= 'xxx')
list_classes[type_obj] is the same thing as the class you want class1 or class2 so it's essentially the same as
A = child1(var_1= 3, var2= 'xxx') # or child2 depending on what type_obj is
Also for some unelicited advice. In the future you might want to reduce the question example to the minimal, reproducable example. For your case your problem had nothing to do with method overloading so you didn't need to include the parent in the example.

Related

Redefining a "subclass" sort of structure using inheritance

I am developing an object oriented application which is very similar to the following limited working example. I am initiating 2 super classes. Class A and class B. Class A defines variables var1 and var2, and contains methods Add, Multiply, Power. Class B defines variables var1 and var2 and contains methods Subtract, Divide and Add.
Class C instantiates an instance of both class A and class B. It then defines a method f1 which utilizes methods from A_obj and B_obj with different names. Notice that method f2 is using the method Add from A_obj and B_obj. The method has the same name but performs a different computation.
The last few lines of the code instantiate an object of class C and then prints out the results using both functions.
class A():
def __init__(self, var1, var2):
self.var1 = var1
self.var2 = var2
def Add(self):
result = self.var1 + self.var2
return result
def Multiply(self):
result = self.var1*self.var2
return result
def Power(self):
result = self.var1**self.var2
class B():
def __init__(self, var1, var2):
self.var1 = var1
self.var2 = var2
def Subtract(self):
result = self.var1-self.var2
return result
def Divide(self):
result = self.var1/self.var2
return result
def Add(self):
result = self.var1+self.var2+self.var1+self.var2
return result
class C():
def __init__(self, var1, var2, var3, var4):
self.A_obj = A(var1,var2)
self.B_obj = B(var3,var4)
def f1(self):
result = self.A_obj.Add()+self.B_obj.Subtract()
return result
def f2(self):
result = self.A_obj.Add()-self.B_obj.Add()
return result
C_obj = C(1, 2, 3,4)
print(C_obj.f1())
print(C_obj.f2())
My question is, can I achieve this sort of functionality using inheritance? Is inheritance even an appropriate concept to use here? I tried forcing it in a previous question but found out that as soon as you use inheritance variables in subclass C become "globally defined" and are recognized by superclasses A and B. I'd like to make sure everything in class A remains local to A and everything in class B remain local to B.

Calling similar named functions in subclasses from superclass

A follow up from this question, which was not very well formulated. The answer provided some additional insight so now I have constructed a limited working example that explains it better.
Basically we have two subclasses A and B and a class C which inherits from both. Classes A and B both have a function MyFunc but which does different things.
I would like for class C to be able to use both functions and have full control of which function is called since I wish to do different things with each function. The comment in the limited working example below shows what I am trying to do.
class A():
def __init__(self, var1, var2):
self.var1 = var1
self.var2 = var2
def MyFunc(self):
result = self.var1 + self.var2
return result
class B():
def __init__(self, var1):
self.var1 = var1
def MyFunc(self):
result = self.var1**2
return result
class C(A,B):
def __init__(self, var1, var2, var3):
A.__init__(self, var1, var2)
B.__init__(self, var3)
def MyFunc(self):
#in this function I want to call MyFunc from A and MyFunc from B. For example to add their results together
How can I call MyFunc in A and MyFunc in B from MyFunc in C?
You can use name mangling to make attributes from a class available in a child class even if that child defines an attribute with the same name.
class A():
def __init__(self, var1, var2):
self.var1 = var1
self.var2 = var2
def __MyFunc(self):
result = self.var1 + self.var2
return result
MyFunc = __MyFunc
class B():
def __init__(self, var1):
self.var1 = var1
def __MyFunc(self):
result = self.var1**2
return result
MyFunc = __MyFunc
class C(A,B):
def __init__(self, var1, var2, var3):
A.__init__(self, var1, var2)
B.__init__(self, var3)
def MyFunc(self):
return self._A__MyFunc() + self._B__MyFunc()
c = C(1, 2, 3)
print(c.MyFunc())
# 14
I tried to make the solution look as simple as possible using your example suggestion.
def MyFunc(self):
result = 0
result += A.MyFunc(self=self)
result += B.MyFunc(self=self)
return result

How would I access variables from one class to another?

I am writing a program that is utilizing multiple classes. I have one class that is dedicated to determining values for a set of variables. I would then like to be able to access the values of those variables with other classes. My code looks as follows:
class ClassA(object):
def __init__(self):
self.var1 = 1
self.var2 = 2
def methodA(self):
self.var1 = self.var1 + self.var2
return self.var1
class ClassB(ClassA):
def __init__(self):
self.var1 = ?
self.var2 = ?
object1 = ClassA()
sum = object1.methodA()
print sum
I use classA to initialize 2 variables (var1 and var2). I then use methodA to add them, saving the result as var1 (I think this will make var1 = 3 and var2 = 2). What I want to know is how would I have ClassB then be able to get the values for var1 and var2 from ClassA?
var1 and var2 are instance variables. That means that you have to send the instance of ClassA to ClassB in order for ClassB to access it, i.e:
class ClassA(object):
def __init__(self):
self.var1 = 1
self.var2 = 2
def methodA(self):
self.var1 = self.var1 + self.var2
return self.var1
class ClassB(ClassA):
def __init__(self, class_a):
self.var1 = class_a.var1
self.var2 = class_a.var2
object1 = ClassA()
sum = object1.methodA()
object2 = ClassB(object1)
print sum
On the other hand - if you were to use class variables, you could access var1 and var2 without sending object1 as a parameter to ClassB.
class ClassA(object):
var1 = 0
var2 = 0
def __init__(self):
ClassA.var1 = 1
ClassA.var2 = 2
def methodA(self):
ClassA.var1 = ClassA.var1 + ClassA.var2
return ClassA.var1
class ClassB(ClassA):
def __init__(self):
print ClassA.var1
print ClassA.var2
object1 = ClassA()
sum = object1.methodA()
object2 = ClassB()
print sum
Note, however, that class variables are shared among all instances of its class.
Can you explain why you want to do this?
You're playing around with instance variables/attributes which won't migrate from one class to another (they're bound not even to ClassA, but to a particular instance of ClassA that you created when you wrote ClassA()). If you want to have changes in one class show up in another, you can use class variables:
class ClassA(object):
var1 = 1
var2 = 2
#classmethod
def method(cls):
cls.var1 = cls.var1 + cls.var2
return cls.var1
In this scenario, ClassB will pick up the values on ClassA from inheritance. You can then access the class variables via ClassA.var1, ClassB.var1 or even from an instance ClassA().var1 (provided that you haven't added an instance method var1 which will be resolved before the class variable in attribute lookup.
I'd have to know a little bit more about your particular use case before I know if this is a course of action that I would actually recommend though...
var1 and var2 is an Instance variables of ClassA. Create an Instance of ClassB and when calling the methodA it will check the methodA in Child class (ClassB) first, If methodA is not present in ClassB you need to invoke the ClassA by using the super() method which will get you all the methods implemented in ClassA. Now, you can access all the methods and attributes of ClassB.
class ClassA(object):
def __init__(self):
self.var1 = 1
self.var2 = 2
def methodA(self):
self.var1 = self.var1 + self.var2
return self.var1
class ClassB(ClassA):
def __init__(self):
super().__init__()
print("var1",self.var1)
print("var2",self.var2)
object1 = ClassB()
sum = object1.methodA()
print(sum)
we can access/pass arguments/variables from one class to another class using object reference.
#Class1
class Test:
def __init__(self):
self.a = 10
self.b = 20
self.add = 0
def calc(self):
self.add = self.a+self.b
#Class 2
class Test2:
def display(self):
print('adding of two numbers: ',self.add)
#creating object for Class1
obj = Test()
#invoking calc method()
obj.calc()
#passing class1 object to class2
Test2.display(obj)
Just create the variables in a class. And then inherit from that class to access its variables. But before accessing them, the parent class has to be called to initiate the variables.
class a:
def func1(self):
a.var1 = "Stack "
class b:
def func2(self):
b.var2 = "Overflow"
class c(a,b):
def func3(self):
c.var3 = a.var1 + b.var2
print(c.var3)
a().func1()
b().func2()
c().func3()
class ClassA(object):
def __init__(self):
self.var1 = 1
self.var2 = 2
def method(self):
self.var1 = self.var1 + self.var2
return self.var1
class ClassB(ClassA):
def __init__(self):
ClassA.__init__(self)
object1 = ClassA()
sum = object1.method()
object2 = ClassB()
print sum

Python, override__getstate__() and __setstate__()

I have these classes:
class Family(object):
__slot__ = ['father', 'var1']
def __init__(self, father, var1 = 1):
self.father, self.var1 = father var1
class Father(object):
__slots__ = ['var2']
def __init__(self, var2 = ''):
self.var2 = var2
father = Father()
family = Family(father = father)
And i want to pickle "family" object. so i need to override __getstate__ and __setstate__
"Family" and "Father" classes.
Can you show me an efficient way of doing this.
(the reason why I use __slots__ is because I have lot of objects and I am trying to save memory)
__getstate__ should return a picklable object (such as a tuple) with enough information to reconstruct the instance.
__setstate__ should expect to receive the same object, and use it to reconfigure the instance.
For example:
import cPickle as pickle
class Family(object):
__slots__ = ['father', 'var1']
def __init__(self, father, var1 = 1):
self.father, self.var1 = father, var1
def __getstate__(self):
return self.father, self.var1
def __setstate__(self, state):
self.father, self.var1 = state
foo = Family('father',1)
foo.var1 = 2
foo_pickled = pickle.dumps(foo)
foo2 = pickle.loads(foo_pickled)
print(repr(foo2))
# <__main__.Family object at 0xb77037ec>
print(foo2.var1)
# 2

Problem with Python nested objects being stored in a dictionary

I'm having some trouble with changing the value of a class at runtime and then instantiating it into an object, then storing that object inside of another class and putting that into python dictionary.
Here is a small code snippet I wrote to illustrate the problem:
import unittest
class cls1(object):
def __init__(self, obj):
self.obj = obj
class cls2(object):
def __init__(self):
self.var = 1
class Testdict(unittest.TestCase):
def __init__(self):
self.objs = dict()
def runTest(self):
obj2 = cls2()
obj1 = cls1(cls2())
self.objs["test1"] = obj1
self.assertEqual(self.objs["test1"].obj.var, 1)
cls2.var = 2
self.assertEqual(cls2.var, 2)
obj1 = cls1(cls2())
self.objs["test2"] = obj1
self.assertEqual(self.objs["test1"].obj.var, 1)
self.assertEqual(self.objs["test2"].obj.var, 2)
if __name__ == "__main__":
d = Testdict()
d.runTest()
Why would cls2 not instantiate with having it's var equal to 2?
I hope this question makes some sense.
What you're showing can't work. Ever.
class Cls2(object):
def __init__(self):
self.var = 1
That's an instance variable. It's not a class variable. You can't access that .var with Cls2.var That variable only exists within each unique instance of the class.
Cls2.var = 2
Does not change the self.var instance variable. That creates a new class variable in the Cls2 class.
You'd need to do something like this.
class Cls2(object):
default= 1
def __init__(self):
self.var = Cls2.default
Now you can do
Cls2.default= 2
And the rest of whatever it is you're doing should work.
Your test would work if cls2 didn't overwrite cls.var when it is instantiated.
Try this:
class cls2(object):
def __init__(self):
try:
self.var
except:
self.var = 1
The try statement just checks to see if you've already set var.

Categories