Как отдать объект в сборку мусора Python? - PullRequest
10 голосов
/ 11 июня 2011

Существует несколько потоков по сборке мусора в Python в SO, и после прочтения около пяти, плюс некоторый документ в режиме онлайн, я все еще не уверен, как работает сборка мусора и как я должен управлять объектами, которые я не использую.Фактически, где-то, что я читаю, никто не должен ничего делать со сборщиком мусора, другие говорят, что нужно del объекты, в то время как другие снова объясняют, что разыменование объекта достаточно для Python, чтобы собрать его как мусор.

Итак,рискуя создать дубликат, я снова задам вопрос, но по-другому, в надежде получить более полную и четкую информацию.

В моем случае я хочу провести небольшую имитацию с объектами, представляющими людей.Будет создано несколько экземпляров класса Person().Он должен существовать в течение некоторого времени, пока он фактически не «умрет», в то время как другие экземпляры будут созданы.

Теперь, как мне сделать этот Person() экземпляр «умершим» (при условии, что многие из этих экземпляров будут созданы, и яне хотите, чтобы эти экземпляры зависали как призраки)?

Есть несколько способов, которыми я могу ссылаться на объект:

john = Person('john')

или

people = []
people.append(Person('john'))

или

people = {}
people['john'] = Person('john')

Как лучше всего содержать мою программу в чистоте, оптимально высвобождая ресурсы?И каков наилучший способ ссылки на мой объект, чтобы я мог контролировать удаление объекта?

Ответы [ 4 ]

9 голосов
/ 11 июня 2011

Может быть, это также может помочь:

>>> # 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

Ссылки: del method ; модуль gc ; модуль слабой связи

8 голосов
/ 11 июня 2011

Ничто из этого не имеет никакого отношения к сбору мусора.

Основной метод управления памятью в Python использует подсчет ссылок .

Вво всех случаях, приведенных выше, Python ведет подсчет всех ссылок на объект, а когда их не осталось, объект удаляется (аналогично std::shared_pointer в C ++).

Уменьшение ссылок когда

  1. объект, содержащий их, либо явно удаляется (через del)
  2. , либо выходит за рамки (см. Также здесь(особенно пример 8)) .

В вашем случае это относится либо к объекту john, либо к любому из people контейнеров.Они выходят из области видимости в конце функции, которая их создала (при условии, что они не return ed для вызывающей функции).В подавляющем большинстве случаев вы можете просто позволить им выйти из области видимости - только когда вы создаете действительно тяжелые объекты или коллекции - скажем, внутри большого цикла - вы можете явно рассмотреть возможность использования del.

Сборка мусора действительно вступает в игру только тогда, когда есть опорных циклов - например, когда объект ссылается на себя.Например:

a = []
a.append(a)

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

4 голосов
/ 11 июня 2011

Я считаю, что большинство программ создают и располагают объекты вполне естественно, поэтому я никогда не беспокоюсь об этом.

Некоторые примеры:

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 в моем примере, которые могли бы поддержать человека. Вы могли бы заставить другие объекты удерживать только имя человека).

0 голосов
/ 09 октября 2018

Предыдущие ответы верны, но вот что рекомендуется в соответствии с python 3.7 Документ :

"Python выполняет автоматическое управление памятью (подсчет ссылок для большинства объектов и сборка мусора для устранения циклов). Память освобождается вскоре после того, как была удалена последняя ссылка на нее. "

Если вам действительно нужно сделать это из-за проблем с управлением памятью, которые возникают у вас в конкретном случае, то импортируйте gc библиотеки и просто сделайте это

     del self.someInstanceOfyourClass
             gc.collect()

вот простой пример https://github.com/nanoseconds/PythonTest/blob/master/test.py

...