2016-07-30 28 views
0

假设我有以下类:如何“推广”一个实例到一个子类?

class Plain(object): 
    def speak(self): 
     print 'ho-hum' 

class Fancy(Plain): 
    def exult(self): 
     print 'huzzah!' 

plain = Plain() 
plain.speak() 
# ho-hum 
plain.exult() 
# --------------------------------------------------------------------------- 
# AttributeError       Traceback (most recent call last) 
# <ipython-input-585-5f782c9ea88b> in <module>() 
# ----> 1 plain.exult() 
fancy = Fancy() 
fancy.speak() 
# ho-hum 
fancy.exult() 
# huzzah! 

...和假设,由于某种原因,我想以“推动”,使其成为Fancy实例的Plain一个实例。

我知道我可以随时修改实例的属性__class__

plain.__class__ = Fancy 
plain.exult() 
# huzzah! 

...但我从不同的SO职位(例如,在这里,这里)聚集,这是不是一件好事做(至少不在生产代码中)。

是否有更多的“生产代码值得”的方式将实例提升为子类?


FWIW,这使我对这个问题的实际使用情况如下。我正在与一个实现Web服务客户端的第三方库合作。这个客户端可以做的事情是返回各种类的实例。这些类提供了很少的方法,而且它们提供的很少。我可以使用更多更强大的方法轻松地为这些类编写子类,但为了使它们变得有用,我还需要为那些当前返回API原始类的实例的API函数编写包装。总而言之,这个包装器只需要将原始(“wrappee”)函数返回的实例提升为我的增强子类的实例。

+1

[?如何转换(继承)父到子类(可能的重复http://stackoverflow.com/questions/10030412/how-to-convert-inherit -parent-to-child-class) – kwarunek

+1

你想要做的是[“状态”设计模式](https://en.wikipedia.org/wiki/State_pattern)。应该有一个容器对象来照顾创建适当类的实例。不要试图通过摆弄低级位来破解。 –

回答

3

你可以使用过程

fancy = Fancy(plain) 

和定义花式的构造函数,如果普通的实例给出的说法应该发生什么。

class Plain: 
    def __init__(self, foo, bar): 
     self.foo = foo 
     self.bar = bar 
     self.status = 'plain' 

class Fancy: 
    def __init__(self, something): 
     if isinstance(something, Plain): 
       self.foo = something.foo 
       self.bar = something.bar 
     self.status = 'fancy' 
+0

对于OP的用例,我会使用包装器(has-a)而不是子类(is-a)。但无论哪种方式,你都会像你已经说过的那样使用Fancy的__init__。 –