Convert a BaseClass object into a SubClass object idiomatically?

前端 未结 2 1867
终归单人心
终归单人心 2020-12-16 20:45

There is a base class Base and a subclass Special.

class Base(object):
    def __init__(self, name):
        self.name = name
    d         


        
2条回答
  •  死守一世寂寞
    2020-12-16 21:35

    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)
    
    

提交回复
热议问题