Как передать объект в сборку мусора python?
Есть несколько потоков в сборке мусора Python в SO, и после прочтения около пяти, а также некоторых документов на линии, я все еще не уверен, как работает сборка мусора и как я должен управлять объектами, которые я не использую. На самом деле, где-то я читал, что ничего не нужно делать с сбором мусора, другие говорят, что нужно del
объектов, а другие снова объясняют, что удаление ссылки на объект достаточно, чтобы Python собирал его как мусор.
Итак, рискуя создать дубликат, я снова задам вопрос, но по-другому, надеясь получить более полную и более ясную информацию.
В моем случае я хочу сделать небольшую симуляцию с объектами, представляющими людей. Будет создано несколько экземпляров класса Person()
. Он должен существовать в течение некоторого времени, пока он фактически "не умрет", пока будут созданы другие экземпляры.
Теперь, как сделать этот Person()
экземпляр "die" (предполагая, что многие из этих экземпляров будут созданы, и я не хочу, чтобы эти экземпляры зависали, как призраки)?
Есть несколько способов, которыми я могу ссылаться на объект:
john = Person('john')
или
people = []
people.append(Person('john'))
или
people = {}
people['john'] = Person('john')
Каков наилучший способ сохранить мою программу в чистоте, оптимально освободив ресурсы? И как лучше всего ссылаться на мой объект, чтобы я мог управлять удалением объекта?
Ответы
Ответ 1
Я нахожу, что большинство программ создают и уничтожают объекты совершенно естественно, поэтому я никогда не беспокоюсь об этом.
Некоторые примеры:
person = Person('john')
person = Person('james')
# Whoops! 'john' has died!
people = []
people.append(Person('john'))
# ...
# All 'Persons' live in people
people = []
# Now all 'Persons' are dead (including the list that referenced them)
class House():
def setOwner(self, person):
self.owner = person
house.setOwner(people[0])
# Now a House refers to a Person
people = []
# Now all 'Persons' are dead, except the one that house.owner refers to.
Я полагаю, что вы следуете за этим:
people = {}
people['john'] = Person('john')
def removePerson(personName):
del people[personName]
removePerson('john')
В этом случае people
является основным списком, и вы можете управлять, когда Person
добавляется и удаляется из списка (его словарь).
Возможно, вам придется продумать концепцию создаваемого человека, а затем умереть очень тщательно: как только созданный, как человек сначала взаимодействует с симуляцией. После смерти, как вы должны распутать ссылки? (Хорошо для человека, чтобы он ссылался на другие вещи, такие вещи, как House
в моем примере, который бы оставил человека в живых. У вас могли бы быть другие объекты, чтобы просто назвать имя человека).
Ответ 2
Возможно, это также может помочь:
>>> # Create a simple object with a verbose __del__ to track gc.
>>> class C:
... def __del__(self):
... print "delete object"
...
>>> c = C()
>>> # Delete the object c successfully.
>>> del c
delete object
>>> # Deletion of an object when it go out of the scope where it was defined.
>>> def f():
... c = C()
...
>>> f()
delete object
>>> c = C()
>>> # Create another reference of the object.
>>> b = c
>>> # The object wasn't destructed the call of del only decremented the object reference.
>>> del c
>>> # Now the reference counter of the object reach 0 so the __del__ was called.
>>> del b
delete object
>>> # Create now a list that hold all the objects.
>>> l = [C(), C()]
>>> del l
delete object
delete object
>>> # Create an object that have a cyclic reference.
>>> class C:
... def __init__(self):
... self.x = self
... def __del__(self):
... print "delete object"
...
>>> c = C()
>>> # Run the garbage collector to collect object.
>>> gc.collect()
9
>>> # the gc.garbage contain object that the gc found unreachable and could not be freed.
>>> gc.garbage
[<__main__.C instance at 0x7ff588d84368>]
>>> # Break the cyclic reference.
>>> c.x = None
>>> # And now we can collect this object.
>>> del c
delete object
>>> # Create another object with cyclic reference.
>>> c = C()
>>> # When closing the interactive python interpreter the object will be collected.
delete object
Refrences: del метод; gc module; модуль weakref
Ответ 3
Ничто из этого не имеет ничего общего с сборкой мусора.
Основной метод управления памятью Python использует подсчет ссылок.
Во всех вышеизложенных случаях Python хранит подсчет всех ссылок на объект, а когда их нет, объект удаляется (аналогично std::shared_pointer
в С++).
Ссылки уменьшаются, когда
В вашем случае это относится либо к объекту john
, либо к любому из контейнеров people
. Они выходят за пределы области действия в конце созданной им функции (при условии, что они не return
ed вызывающей функции). В большинстве случаев вы можете просто позволить им выйти из сферы действия - только когда вы создаете действительно тяжелые объекты или коллекции - скажем, в большой петле - вы можете явно рассмотреть использование del
.
Сбор мусора действительно вступает в игру только тогда, когда есть ссылочные циклы
- например, когда объект ссылается на себя. Как:
a = []
a.append(a)
Опять же, это происходит автоматически, и вам не нужно делать ничего особенного.