Изменение экземпляра класса внутри метода экземпляра

Любая идея, если есть способ заставить следующий код работать

class Test(object):

    def __init__(self, var):
        self.var = var

    def changeme(self):
        self = Test(3)

t = Test(1)
assert t.var == 1
t.changeme()
assert t.var == 3

- это что-то вроде следующего безопасного использования для более сложных объектов (например, моделей django, для горячей замены записи db, на которую ссылается экземпляр)

class Test(object):

    def __init__(self, var):
        self.var = var

    def changeme(self):
        new_instance = Test(3)
        self.__dict__ = new_instance.__dict__

t = Test(1)
assert t.var == 1
t.changeme()
assert t.var == 3

Ответ 1

self = Test(3) повторно привязывает локальное имя self, без эффектов, наблюдаемых извне.

Назначение self.__dict__ (если вы не говорите о экземплярах с __slots__ или из классов с нетривиальными метаклассами) обычно нормально, и поэтому self.__init__(3) повторно инициализирует экземпляр. Однако я предпочел бы иметь конкретный метод self.restart(3), который знает, который вызывается в уже инициализированном экземпляре, и делает все, что необходимо для удовлетворения этого конкретного и необычного случая.

Ответ 2

Нет, и нет.

Сказав это, вы можете изменить класс, но не делайте этого.

Ответ 3

Бывший код работает, за исключением того, что он не будет делать много, потому что он просто заменяет объект с именем "я" в пределах области changeme(). Имена Python не привязаны к значениям, они всегда относятся к их объему или пространству имен.

Чтобы сделать то, что вы хотите, вам нужно иметь доступ к имени вне класса, которое вы могли бы назначить из него:

class Test:
  def changeme(self):
    global myclass
    myclass = Test(3)

myclass = Test(2)
myclass.changeme()
print myclass # 3

В основном это просто перезаписывает имя "myclass", чтобы указать на новый экземпляр. Он не "перезаписывает" первый экземпляр, как вы думаете. Старый экземпляр все еще живет и будет собираться мусором, если не упоминается в другом месте.