Python, override__getstate__() and __setstate__() - python

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

Related

Dynamically created instances in 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.

How do I pass the same variable(iterable) between instances of different classes(that inherits from the same parent)

I want to pass a variable(iterable )between instances of different classes. I have a structure similar with the one below.
Each class has its own module(so no globals) and needs to work in python 3 and 2.
class O:
pass
class A(O):
pass
class B(O):
def __init__(self, cache):
self.cache = cache
class B1(B):
def p(self):
self.cache.add_to_cache("32", "something something")
class B2(B):
def p(self):
self.cache.get_from_cache("52", "something else")
For B and its sub-classes I want to create a cache. All instances of this classes(B, B1, B2) to use the same cache.
To keep it simple, let's say that the cache is just a dict.
c = {}
a = A(c)
b1 = B() - needs c
b1.p()
b2 = C() - needs c
b2.p()
print(cache)
Off course the example above, is wrong because the cache is different for each instance.
The chache should be :
{
"32", "something something"
"52": "something else"
}
Another approach to this is using CacheService as an injectable Singleton service, which I consider a better practice.
Read this first for a code/syntax solution to your direct question, or continue reading for a solution with better design.
class O(object):
pass
class CacheService(object):
__instances = {}
#staticmethod
def getinstance(owner_id):
if owner_id not in CacheService.__instances:
CacheService.__instances[owner_id] = CacheService(owner_id)
return CacheService.__instances[owner_id]
def __init__(self, owner_id):
self._owner_id = owner_id
self._owner_query = CacheService.__name__ + self._owner_id
self._cache = {}
def put_in_cache(self, key, value):
self._cache[self._owner_query + str(key)] = value
def get_from_cache(self, key):
return self._cache.get(self._owner_query + str(key), "the_default")
class B(O):
def __init__(self):
self._cache = CacheService.getinstance(B.__name__)
class B1(B):
def __init__(self):
super(B1, self).__init__()
def p(self):
val1 = self._cache.get_from_cache("a")
print(val1)
class B2(B):
def __init__(self):
super(B2, self).__init__()
def p(self):
self._cache.put_in_cache("a", 2)
if __name__ == "__main__":
b1 = B1()
b2 = B2()
b2.p()
b1.p()
out:
2
This still uses a class variable, but hides it from your "everyday code", and moves it to the "infrastructure level".
I see this as cleaner, as now your class hierarchy shouldn't handle its own global variables.
To directly answer the programming question, Use class variables.
As a side note, it would be much better to use some kind of "CacheService" and inject that to the constructor, rather than use inheritance and class variables.
For this, see my other answer.
Code for using class variables follows:
class O(object):
pass
class B(O):
__cache = {} # use your cache class if you want, I am using dict just for show
def __init__(self):
pass
def _get_from_cache(self, key):
return self._cache.get(key, "default1")
def _put_in_cache(self, key, value):
self._cache[key] = value
class B1(B):
def __init__(self):
super(B1, self).__init__()
def p(self):
val1 = self._get_from_cache("a")
print(val1)
class B2(B):
def __init__(self):
super(B2, self).__init__()
def p(self):
self._put_in_cache("a", 2)
if __name__ == "__main__":
b1 = B1()
b2 = B2()
b2.p()
b1.p()
out:
2
Notice _get_from_cache and _put_in_cache are methods, but they can be #staticmethods, as they only ever access class variables, and their self isn't "really" ever being used. __cache could theoretically be accessed directly by children, but the _get_from_cache and _put_in_cache makes __cache private, and gives a protected API to it.

Python: pass whole self of class to init of new class

I have a class and a sub-class, I'd like to pass the whole of the self of the class to the sub-class. I can pass self over to the new class explicitly easily enough, e.g.
class foo:
def __init__(self, a, b):
self.a = a
self.b = b
self.c = 'foo'
def foo_method(self):
print('a foo method')
class bar(foo):
def __init__(self, foo_object):
self.a = foo_object.a
self.b = foo_object.b
self.c = foo_object.c
def bar_method(self):
print('a bar method')
foo_object = foo(a = 'a', b = 'b')
bar_object = bar(foo_object)
bar_object.a
Is there a more succinct way to pass these over? Something like:
class bar(foo):
def __init__(self, foo_object):
self = self.foo_object
Update:
Thanks https://stackoverflow.com/users/10104112/bastien-antoine, the following solution worked:
class bar(foo):
def __init__(self, foo_object):
self.__dict__ = foo_object.__dict__.copy()
def bar_method(self):
print('a bar method with ' + str(self.c))
Have you tried the copy builtins library?
Otherwise I think you can easily implement your own .copy() method that would copy the values from the old object __dict__ to the new one. Something like this:
class MyObject:
a = None
def set_default_values(self):
self.a = 1
def copy(self, old):
if type(self) == type(old):
self.__dict__ = old.__dict__.copy()
else:
raise TypeError('Wrong type')
if __name__ == "__main__":
obj_1 = MyObject()
print(obj_1.a)
obj_1.set_default_values()
print(obj_1.a)
obj_2 = MyObject()
print(obj_2.a)
obj_2.copy(obj_1)
print(obj_2.a)
Note that I've added a type checking to be sure that you copy attributes that would exist otherwise, but I think simply self.__dict__ = old.__dict__.copy() would work fine, thought you might end up with attributes you might not suppose to have in the new object.
Hope this helps!
I think that you can do that with
class bar(foo):
def __init__(self):
super(bar, self).__init__()
with this code, you ran the init function for the subclass

How to inherit every class in python?

I'm working with classes that have a lot of instance variables, and I want to have classes that inherit every instance variables from them. something like this:
class foo(object):
def __init__(self,thing1,thing2,thing3,thing4,thing5,thingetc):
self.1 = thing1
self.2 = thing2
self.3 = thing3
self.4 = thing4
self.5 = thing5
self.etc = thingetc
class bar(foo):
self.6 = []
a = bar
print a.3
obviously this won't work, but all the documentation that I can find on line is confusing. How do you inherit variables in cases like this?
Currently, your code is invalid syntax as a digit cannot be at the very front of a variable name. However, you can use *args with __dict__:
class foo:
def __init__(self, *args):
self.__dict__ = dict(zip(['var{}'.format(i) for i in range(1, len(args)+1)], args))
f = foo(*range(15))
print(f.var1)
print(f.var14)
Output:
0
13
Use this as a template for your inheritance, emphasis on the super() method:
class Foo:
def __init__(self):
self.name = 'Foo'
class Bar(Foo):
def __init__(self):
super().__init__()
b = Bar()
b.name
# outputs 'Foo'
For your specific type of class (that takes an unknown number of initialization arguments, i.e. *args):
class Foo:
def __init__(self, *args):
self.name = 'Foo'
for i, arg in enumerate(args):
setattr(self, 'thing_' + str(i), arg)
class Bar(Foo):
def __init__(self, *args):
super().__init__(*args)
b = Bar('hello', 'world')
b.name
# outputs 'Foo'
b.thing_0
# outputs 'hello'
b.thing_1
# outputs 'world'
Now I would personally use the **kwargs over *args for specifying unique instance attributes:
class Foo:
def __init__(self, **kwargs):
self.name = 'Foo'
for att in kwargs:
setattr(self, att, kwargs[att])
class Bar(Foo):
def __init__(self, **kwargs):
super().__init__(**kwargs)
b = Bar(value = 4, area = 3.14)
b.name
# outputs 'Foo'
b.value
# outputs 4
b.area
# outputs 3.14

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

Categories