1

Possible Duplicate:
Python dynamic inheritance: How to choose base class upon instance creation?

I want a class to choose a base class on the fly based on a parameter in the init method.

Class A():
    #...
Class B():
    #...
Class C():
    def __init__(self, base_type):
        if parent_type == 'A':
            #TODO: make C derive A
        else:
            #TODO: make C derive B

A and B are library classes that derive the same base class.

The answers to a similar question seemed too ugly.

Community
  • 1
  • 1
travis1097
  • 2,829
  • 5
  • 23
  • 23
  • 3
    Why would you do something like this? Although many things are possible in a dynamic language like python, this does not seem as a good way to go with. With some more context, we might be able to better understand your problem and offer a solution. – cyroxx Aug 23 '12 at 20:18
  • 5
    Do you really need to use inheritance? Could you use composition instead (e.g. have each C instance own an instance of either A or B)? Check out the second, highly rated answer to the question you linked. – Blckknght Aug 23 '12 at 20:21
  • 5
    If you insist on not using a factory pattern, you may want to investigate metaclasses. http://docs.python.org/py3k/reference/datamodel.html#metaclasses – dsh Aug 23 '12 at 20:22
  • 1
    @cyroxx I just added an important detail that A and B are library classes that derive the same base class. – travis1097 Aug 23 '12 at 20:36
  • 5
    Similar question is more or less exactly the same, and provides all the answers you're going to get here... if the answer is 'ugly', your question should address what you find ugly about those soltuions, not just 'give me new answers to the same question'. – Hamish Aug 23 '12 at 20:38

3 Answers3

2

I assume you mean base_type insteand of parent type. But the following should work

Class C():
    def __init__(self, base_type):
        if base_type == 'A':
            self.__class__=A
        else:
            self.__class__=B

Some more details on this approach can be found here: http://harkablog.com/dynamic-state-machines.html

schacki
  • 9,401
  • 5
  • 29
  • 32
2

While you can change the class in __init__, it's more appropriate to do it in __new__. The former is for initialising, the latter for construction:

class A(object): pass
class B(object): pass

class C(object):
    def __new__(cls, base_type, *args, **kwargs):
        return super(C, cls).__new__(base_type, *args, **kwargs)

assert isinstance( C(A), A )
assert isinstance( C(B), B )

With __init__, you're creating an instance of C, and then modifying its type. With __new__, you're never creating an instance of C, just the required base_type.

Matthew Trevor
  • 14,354
  • 6
  • 37
  • 50
0

I am completely agree with cyroxx, you should give us some context to your problem. As it stands now, __init__ is called after the instance of the class is created to initialize its members. Too late to change the inheritance.

Would a simple class factory be enough for you:

class MyA(ABMixin, A): pass

class MyB(ABMixin, B): pass

def factory(class_type):
    if class_type == 'A':
        return MyA()
    else:
        return MyB()

I suggest to read this SO answer about dynamic class creation in python.

Community
  • 1
  • 1
alex vasi
  • 5,304
  • 28
  • 31