Мутировать объект в экземпляр одного из его подклассов - PullRequest
2 голосов
/ 22 мая 2010

Возможно ли преобразовать объект в экземпляр производного класса класса объекта инициала? Что-то вроде:

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...

Если это невозможно, как мне поступить иначе?
Моя проблема заключается в следующем: Мой базовый класс похож на «сводку», а класс Derived - это «все». Конечно, получить «целую вещь» немного дороже, поэтому работа с резюме так долго, насколько это возможно, имеет смысл иметь эти два класса. Но вы должны иметь возможность получить его, если хотите, и тогда нет смысла иметь сводку больше, поэтому каждая ссылка на сводку должна теперь быть (или содержать, по крайней мере) всю вещь. Я думаю, мне нужно создать класс, который может содержать оба, верно?

class Thing():
    def __init__(self):
        self.summary = Summary()
        self.whole = None

    def get_whole_thing(self):
        self.whole = Whole()

Ответы [ 4 ]

6 голосов
/ 22 мая 2010

Отвечая на исходный вопрос, поставив его, изменив метод mutate на:

def mutate(self):
    self.__class__ = Derived

сделает именно то, что было запрошено - измените класс self на Derived вместо Base. Это не выполняет автоматически Derived.__init__, но при желании его можно явно вызвать (например, как self.__init__() как второе выражение в методе).

Является ли это хорошим подходом к реальной проблеме ОП - это совершенно другой вопрос, чем первоначальный вопрос, который был

Возможно ли изменить объект в экземпляр производного класса класс объекта инициала?

Ответ на это «да, это возможно» (и это сделано так, как я только что показал). «Это лучший подход для моей конкретной прикладной проблемы» - это вопрос , отличный от , чем «возможно ли это»; -)

6 голосов
/ 22 мая 2010

Общий подход ООП состоит в том, чтобы сделать итоговый объект Фасадом, который делегирует дорогостоящие операции (динамически создаваемому) внутреннему объекту. Вы могли бы даже сделать его полностью прозрачным, чтобы вызывающие объекты не видели, что там происходит (ну, конечно, если они не начинают рассчитывать время).

1 голос
/ 22 мая 2010

Я забыл сказать, что я также хотел иметь возможность создавать "целую вещь" с самого начала, а не сводку, если она не нужна. Я наконец сделал это так:

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

Работает как шарм:)

0 голосов
/ 22 мая 2010

Вы не можете присвоить self, чтобы делать то, что вы хотите, но вы можете изменить класс объекта, назначив self.__class__ в вашем методе mutate.

Однако это действительно плохая практика - для вашей ситуации делегирование лучше, чем наследование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...