There is a base class Base and a subclass Special.
class Base(object):
def __init__(self, name):
self.name = name
d
You can achieve this by defining an alternate constructor and reassigning the instance's __class__ attribute.
class Base(object):
def __init__(self, name):
self.name = name
def greet(self):
return 'Hello %s' % self.name
@classmethod
def alt_constructor(cls, *args, **kwargs):
obj = cls(*args, **kwargs)
obj.__class__ = Special
return obj
class Special(Base):
def __init__(self, name):
super(Special, self).__init__(name)
def rhyme(self):
return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name
>>> s = Base.alt_constructor("test")
>>> print s.rhyme()
Hi test! How are you? Fine, thanks. What about you?
EDIT:
Moved the constructor from Special to Base.
If you can't modify the Base class you can add a classmethod to Special that will change the class of any object passed to it.
class Base(object):
def __init__(self, name):
self.name = name
def greet(self):
return 'Hello %s' % self.name
class Special(Base):
def __init__(self, name):
super(Special, self).__init__(name)
def rhyme(self):
return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name
@classmethod
def convert_to_special(cls, obj):
obj.__class__ = Special
>>> b = Base("test")
>>> print type(b)
>>> Special.convert_to_special(b)
>>> print type(b)
A more all purpose solution would be to create a mixin that can be added to any class.
class ConverterMixin(object):
@classmethod
def convert_to_class(cls, obj):
obj.__class__ = cls
class Special(ConverterMixin, Base):
def __init__(self, name):
super(Special, self).__init__(name)
def rhyme(self):
return 'Hi %s! How are you? Fine, thanks. What about you?' % self.name
>>> b = Base("test")
>>> print type(b)
>>> Special.convert_to_class(b)
>>> print type(b)