Является ли переопределение __del__() лучшим выбором здесь?

Я пытаюсь найти лучший способ удалить что-то, желательно без необходимости писать много кода.

В моем проекте я моделирую химические соединения - у меня есть Element случаи связаны с другими Element случаи через Bond пример. В химии связи часто ломаются, и я хотел бы иметь чистый способ сделать это. Мой текущий метод выглядит примерно так

# aBond is some Bond instance
#
# all Element instances have a 'bondList' of all bonds they are part of
# they also have a method 'removeBond(someBond)' that removes a given bond 
# from that bondList
element1.removeBond(aBond)
element2.removeBond(aBond)
del aBond

Я хочу сделать что-то вроде

aBond.breakBond()

class Bond():
    def breakBond(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
        del self

С другой стороны, что-то вроде этого было бы хорошо

del aBond

class Bond():
    def __del__(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
        del self

Любой из этих способов сделать это предпочтительнее других, или есть какой-то другой способ сделать это, что я пропускаю?

2 ответа

Решение

Python использует сборщик мусора для управления памятью, что означает, что вам не нужно ничего удалять. Этот класс в порядке:

class Bond():
    def breakBond(self):
        self.start.removeBond(self)
        self.end.removeBond(self)

Обратите внимание, что del не удаляет ничего из памяти! Он просто удаляет ссылку на объект, но объекты могут иметь более одной ссылки:

>>> some_list = [1,2,3]
>>> b = some_list
>>> del b   # destroys the list?
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>> some_list   # list is still there!
[1, 2, 3]
>>> c = some_list
>>> del some_list
>>> c        # list is still there!
[1, 2, 3]
>>> del c

После последнего del c переводчик может освободить список. В CPython освобождение будет выполнено немедленно (в этом простом случае), однако в другой реализации языка интерпретатор может не освободить список немедленно.

Также обратите внимание, что __del__ Документация цитирует этот факт. Более того, это действительно низкоуровневый метод, который вам не нужен в 99,9% случаев, поэтому он, безусловно , не является правильным способом справиться с вашей ситуацией.

Первый способ довольно утомителен и подвержен ошибкам. Второй в порядке, но del self в Bond.breakBond совершенно и совершенно бессмысленно (подробнее об этом ниже). Третий хакерский, ненадежный, и в данном конкретном случае вообще не работает (из-за круговой ссылки между Бондом и Элементами, __del__ никогда не вызывается, пока вы не обновитесь до Python 3.4, но даже тогда он остается хакерским и ненадежным).

del name удаляет только местный name не вызывает __del__ или иным образом повлиять на объект. Это абсолютно не влияет на управление памятью, за исключением возможности более раннего сбора мусора, если name была последней (достижимой) ссылкой.

Вы должны сделать это:

aBond.breakBond()

class Bond():
    def breakBond(self):
        self.start.removeBond(self) # refers to the first part of the Bond 
        self.end.removeBond(self) # refers to the second part of the Bond 
Другие вопросы по тегам