Удаление атрибутов при удалении экземпляра - PullRequest
1 голос
/ 02 февраля 2010

класс А: def __get (self): вернуть self._x

 def __set(self, y):
  self._x = y

 def __delete_x(self):
  print('DELETING')
  del self._x

 x = property(__get,__set,__delete_x)

b = A()

# Here, when b is deleted, i'd like b.x to be deleted, i.e __delete_x()
# called (and for immediate consequence, "DELETING" printed)
del b

Ответы [ 3 ]

2 голосов
/ 02 февраля 2010

Семантика оператора del на самом деле не поддается тому, что вы хотите здесь. del b simple удаляет ссылку на объект A, который вы только что создали, из рамки / словаря локальной области видимости; это напрямую не приводит к выполнению каких-либо операций над самим объектом. Если это была последняя ссылка на объект, то счетчик ссылок, упавший до нуля, или сборщик мусора, собирающий цикл, может привести к освобождению объекта. Вы можете наблюдать это, добавив к объекту метод __del__ или добавив обратный вызов слабый , который выполняет нужные действия.

Ни одно из последних двух решений не кажется отличной идеей; __del__ методы не позволяют сборщику мусора собирать циклы, связанные с объектом; и хотя слабые ссылки не страдают от этой проблемы, в любом случае вы можете работать в странной среде (например, во время завершения работы программы), что может затруднить выполнение того, чего вы хотите достичь.

Если вы можете расширить свой конкретный вариант использования, возможно, что существует совершенно другой подход к достижению желаемой конечной цели, но трудно предположить на основе такого общего и ограниченного примера.

1 голос
/ 02 февраля 2010

Чтобы контролировать, что происходит, когда экземпляр класса A исчезает (будь то удаление или сборка мусора), вы можете реализовать специальный метод __del__(self) в A. Если вы хотите, чтобы ваш код включался при исчезновении определенного атрибута этого экземпляра, вы можете либо обернуть этот атрибут классом-оболочкой, который имеет __del__, либо, возможно, лучше в большинстве случаев использовать слабый модуль (однако, не все типы могут быть объектом слабых ссылок, поэтому вам также может понадобиться некоторая упаковка для этого случая).

Избегать __del__ обычно предпочтительнее, если возможно, потому что это может помешать сборке мусора и, таким образом, вызвать «утечки памяти», если и когда у вас есть циклические ссылки.

0 голосов
/ 02 февраля 2010

Безобразный способ сделать это будет:

def __del__(self):
    for x in dir(self.__class__):
        if type(getattr(self.__class__, x)) == property:
            getattr(self.__class__, x).fdel(self)
...