GhostKU
GhostKU

Reputation: 2108

How to convert class to it's child in Python?

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

Answers (2)

Robᵩ
Robᵩ

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

Arctelix
Arctelix

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

Related Questions