1

Is there a way to change objects class dynamically depending on passed variable? For example:

class Parent:
    def __init__(self, variable):
        ...
        some magic
        ...

class ChildA:
    pass

class ChildB:
    pass


cls=Parent('a')
cls.__class__
<class '__main__.ChildA'>

cls=Parent('b')
cls.__class__
<class '__main__.ChildB'>
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
Adogyf
  • 165
  • 2
  • 9
  • 1
    Consider whether these should actually be separate classes at all, and if they should be, consider whether it might be better to create instances through a factory function of some sort instead of `Parent(whatever)`. – user2357112 Mar 22 '17 at 22:43
  • 1
    A simple google search brought up [this](http://stackoverflow.com/questions/9143948/changing-the-class-type-of-a-class-after-inserted-data). Google is your friend. – Shachar Ohana Mar 22 '17 at 22:44

2 Answers2

2

This can be done in a __new__ method for the Parent class. It gets to make the decisions about what object is really created:

class Parent(object):
    def __new__(cls, selector):
        if selector == 'a':
            return object.__new__(A)
        else:
            return object.__new__(B)

class A(Parent):
    letters = 'aaaaa'

class B(Parent):
    letters = 'bbbbb'

a = Parent('a')
print(a.letters)
b = Parent('b')
print(b.letters)

The output proves that it works:

aaaaa
bbbbb
Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • Anyone downvoting a python core developer answer should have the courage to explain _why_ they think this is a bad answer. – msvalkon Mar 23 '17 at 08:49
1

Define a conditional check if, else in the __new__ function of class parent prior to the __init__.

class Parent(Object):
   def __new__(self,s):
       if s=='a':
         return object.__new__(childA)
       else:
         return object.__new__(childB)
class childA(Parent):
   pass
class childB(Parent):
   pass
Amal Vincent
  • 154
  • 1
  • 10