有一个基类Base
和一个子类Special
。
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
如何将Base
的实例转换为实例Special
?目前我在classmethod
上定义了Special
,只需重新__dict__
:
class Special(Base):
...
@classmethod
def from_base(cls, baseobj):
special = Special()
special.__dict__ = baseobj.__dict__
return special
这是惯用的吗?如果不是会是什么?
P.S。示例场景:基类是一些默认实现。在野外,您可能会找到基类的对象。现在在某个项目中,基类已经是子类,并且已经在子类中添加了特殊方法。现在你仍然主要使用基类对象,但有时你会想要“升级”到特殊类,因为你需要访问一些方法。
答案 0 :(得分:7)
您可以通过定义备用构造函数并重新分配实例的__class__
属性来实现此目的。
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?
修改强>
将构造函数从Special
移至Base
。
如果您无法修改Base
类,可以向Special
添加一个类方法,该类方法将更改传递给它的任何对象的类。
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)
<class '__main__.Base'>
>>> Special.convert_to_special(b)
>>> print type(b)
<class '__main__.Special'>
更全能的解决方案是创建一个可以添加到任何类的mixin。
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)
<class '__main__.Base'>
>>> Special.convert_to_class(b)
>>> print type(b)
<class '__main__.Special'>
答案 1 :(得分:1)
无论如何,这是代码:
>>> base = Base("I'm a base!")
>>> hasattr(base, 'rhyme')
False
>>> base.__class__ = Special
>>> hasattr(base, 'rhyme')
True
>>> base.rhyme()
"Hi I'm a base!! How are you? Fine, thanks. What about you?"