Как передать объект в сборку мусора 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)

Опять же, это происходит автоматически, и вам не нужно делать ничего особенного.