将对象转换为其子类实例
有没有办法把一个对象变成它原本类的子类的实例?就像这样:
class Base():
def __init__(self):
self.a = 1
def mutate(self):
self = Derived()
class Derived(Base):
def __init__(self):
self.b = 2
但是这样不行。
>>> obj = Base()
>>> obj.mutate()
>>> obj.a
1
>>> obj.b
AttributeError...
如果这样不行,那我该怎么做呢?
我的问题是这样的:我的基类就像是一个“摘要”,而派生类则是“完整的内容”。当然,获取“完整的内容”是比较耗费资源的,所以尽可能地处理摘要是这两个类存在的意义。但是如果你想要获取完整的内容,那摘要就没什么意义了,所以所有对摘要的引用现在应该是(或者至少包含)完整的内容。我想我需要创建一个可以同时保存这两者的类,对吧?
class Thing():
def __init__(self):
self.summary = Summary()
self.whole = None
def get_whole_thing(self):
self.whole = Whole()
4 个回答
6
一种常见的面向对象编程方法是把摘要对象设计成一个“外观”,它负责把一些复杂的操作转交给一个后端对象(这个后端对象是动态构建的)。你甚至可以让这个过程对使用这个对象的人来说是完全透明的,也就是说,他们不会察觉到有什么特别的事情发生(当然,除非他们开始计时来观察性能)。
8
针对最初提出的问题,如果把 mutate
方法改成这样:
def mutate(self):
self.__class__ = Derived
就能完全满足要求——把对象的类从 Base
改成 Derived
。不过,这样并不会自动执行 Derived.__init__
方法,如果需要的话,可以手动调用(比如在方法的第二行写 self.__init__()
)。
至于这种做法是否对提问者的实际问题是个好方法,那就和最初的问题完全不同了,最初的问题是:
能不能把一个对象变成它原本类的派生类的实例?
这个问题的答案是“可以,确实可以”(而且就是我刚才展示的那种方法)。而“这对我具体的应用问题来说是最佳方法吗”是一个不同的问题,和“是否可能”是两回事;-)
1
我忘了说,我还想从头开始创建一个“完整的东西”,而不是在不需要的时候只做个总结。
我最终是这样做的:
class Thing():
def __init__(self, summary=False):
if summary:
self.summary = "summary"
self._whole = None
else:
self._whole = "wholething"
@property
def whole(self):
if self._whole: return self._whole
else:
self.__init__()
return self._whole
效果非常好 :)