M.Love
M.Love

Reputation: 31

How can I change at runtime a type of object with python

I have a problem with my code. I want to apply the multiply inheritance in Python and I want to change the type of object instance at runtime with a method. For example:

class MyClassA:
    def method(self):
        #method A

class MyClassB:
    def method(self):
        #method B

class MyClassC(MyClassA, MyClassB):
    def check():
        ...
        if isinstance(my_instance, MyClassA):
            #now you will use method of MyClassB
        else:
            # now you will use method of MyClassA

But this work only in the MyClass scope. How can I solve it?


UPDATE Thank you every one for the response. I try to be more clear. I have MyClassA and MyClassB with same methods. I want to use with the same object of MyClassC, in same cases method of MyClassA and in other cases method of MyClassB. So, at begin instance_classC.method() calls the method of MyClassA. After I have called instance_classC.check(), I want that, calling instance_classC.method(), this instruction calls the method of MyClassB.

Upvotes: 1

Views: 879

Answers (2)

Sam Hartman
Sam Hartman

Reputation: 6489

class MyClassC(MyClassa, MyClassB):

    def check(self):
        self.use_b_methods = True

    def __init__(self):
        super().__init__()
        self.use_b_methods = False

    def method(self):
        if self.use_b_methods: return MyClassB.method(self)
        else return MyClassA.method(self)

That will select which method to use based on a variable in the class. That is not actually changing the type of a object at runtime. As a reminder, when you select a method directly from a defining class, you get an unbound method and need to pass in the self object rather than having it supplied for you.

You can change te runtime class of an object by changing class of an instance

instance = MyType()
instance.__class__ = MyOtherType()

However, there are restrictions on when you can change class_, and there are some significant pitfalls to doing that. You haven't described a situation in your question where you need to change __class, so I'd recommend an approach like I have described.

Upvotes: 0

hpaulj
hpaulj

Reputation: 231385

With this simple inheritance:

In [351]: class A(object):
     ...:     def foo(self):
     ...:         print("<A>")
     ...:         
In [352]: class B(object):
     ...:     def foo(self):
     ...:         print('<B>')
     ...:         
In [353]: class C(A,B):
     ...:     pass
     ...: 
In [354]: c=C()
In [355]: c.foo()
<A>

as a default c used the A.foo method.

Note that instance is True for C, and both supers.

In [356]: isinstance(c,C)
Out[356]: True
In [357]: isinstance(c,A)
Out[357]: True
In [358]: isinstance(c,B)
Out[358]: True
In [359]: c.__class__
Out[359]: __main__.C

If I refine C, I can choose the default super method, or specifically choose the method from of the parents.

In [366]: class C(A,B):
     ...:     def foo(self):
     ...:        print('<C>')
     ...:        super().foo()
     ...:        A.foo(self)
     ...:        B.foo(self)

In [367]: c=C()
In [368]: c.foo()
<C>
<A>
<A>
<B>

More on using super, see Better way to access super class method in multiple inheritance

I'm sure it's been discussed other SO questions.

If I'm trying to clarify the wrong question, you'll need to give more details about the problem that you are trying to solve.

Upvotes: 1

Related Questions