Изменить экземпляр класса внутри метода экземпляра - PullRequest
7 голосов
/ 26 января 2010

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

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, для горячей замены записи в БД, на которую ссылается экземпляр)

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

Ответы [ 3 ]

7 голосов
/ 26 января 2010

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

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

3 голосов
/ 26 января 2010

Нет и нет.

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

2 голосов
/ 26 января 2010

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

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

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

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

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

...