将对象转换为其子类实例

4 投票
4 回答
2034 浏览
提问于 2025-04-15 23:01

有没有办法把一个对象变成它原本类的子类的实例?就像这样:

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

效果非常好 :)

撰写回答