Reputation: 2108
I have a class called class_A
I do some work with it and store it with pickle
.
I have another class class_B
which is a child of class_A
but has some additional methods and properties. I want to load data from my pickled file as class_B
and work with it. How can I do it?
Upvotes: 0
Views: 58
Reputation: 168626
You could override the unpickler's find_class
function, like so:
import pickle
# Set up class_A and class_B as in the question
class class_A:
def __init__(self):
self.a = 1
def method_a(self): pass
class class_B(class_A):
def __init__(self):
super().__init__()
self.b = 1
def method_b(self): pass
# Create an pickle a class_A object
a = class_A()
with open('pickle', 'wb') as f:
pickle.dump(a, f)
# Create an unpickler that lies about class types
class MyUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if (module, name) == ('__main__', 'class_A'):
name = 'class_B'
return pickle.Unpickler.find_class(self, module, name)
# Unpickle with the transmorgifying unpickler
with open('pickle', 'rb') as f:
new_b = MyUnpickler(f).load()
# Verify that the returned object is a `class_B`
assert isinstance(new_b, class_B)
assert hasattr(new_b, 'method_a')
assert hasattr(new_b, 'method_b')
assert hasattr(new_b, 'a')
# Sadly, new_b.__init__ never ran, so no `new_b.b`
assert not hasattr(new_b, 'b')
Reference: https://docs.python.org/3/library/pickle.html#pickle.Unpickler.find_class
Upvotes: 2
Reputation: 4576
More details around your exact use case are needed to be certain, but one of these abstract approaches may work for you.
b = Class_B()
b.__dict__ = pickled_data
Or
b = Class_B(**pickled_data)
Or
a = Class_A()
b = Class_B()
b.__dict__ = a.__dict__
I'd recommend crating a class method to do what you need.
b = B.from_a(class_a, *args, **kwargs)
Upvotes: 0