Python : Convert Superclass instance to Subclass

I am given an object a of the class A. I do not understand how class A works. Furthermore an unknown number of methods throughout the module I am using use A. So for all practical purposes A is unknown and we can only manipulate an instance of it and one known method, method2.

I am given an instance a. I want to convert a to a class B such that it remains identical in every respect except that method2 (which was present in the original class A and prints a) now prints b. How do I modify the piece of code below to be able to do that ?

class B(A):
    def __init__(self,**kwargs):
        super().__init__(**kwargs)

    def method2(self):
        print('b')

a.method1() #prints '1'
a.method2() #prints 'a'
print(a[0]) #prints 1
#a = convertAtoB(a)
a.method1() #prints '1'
a.method2() #should print 'b'
print(a[0]) #prints 1

I am aware of a previous answer to a similar question which involved using __getattr__ however when trying the below piece of code:

class B(object):
    def __init__(self, a):
        self.__a = a

    def __getattr__(self, attr):
        return getattr(self.__a, attr)

    def __setattr__(self, attr, val):
        object.__setattr__(self, attr, val)
    
    def method2(self):
        print('b')

I got, in the practical problem I am having, the error TypeError: 'B' object is not subscriptable.

edit : added a subscript test, as I mentioned above, I don’t entirely understand how A works or which methods in the imported module need A to work.

Answer

You can reassign object’s __class__ to a new type. I’ve put comment inside the code: (take care of object initialization yourself if necessary)

class A:
    def func_A_1(self):
        return 'func_A_1 is running'

    def func_A_2(self):
        return 'func_A_2 is running'

    def method2(self):
        return 'method2 of class A'


class B(A):
    def method2(self):
        return 'method2 of class B'


obj = A()

print(obj)
print(obj.func_A_1())
print(obj.method2())
print('------------------------------')

# turning object of A to B
obj.__class__ = B
print(obj)

# still have access to A's methods
print(obj.func_A_1())

# This method is now for B
print(obj.method2())

output :

<__main__.A object at 0x0000012FECFACFD0>
func_A_1 is running
method2 of class A
------------------------------
<__main__.B object at 0x0000012FECFACFD0>
func_A_1 is running
method2 of class B