2011-06-11 11 views
10

Hay varios subprocesos en la recolección de basura de Python en SO, y después de leer aproximadamente cinco, más algunos documentos en línea, todavía no estoy seguro de cómo funciona la recolección de basura y cómo debo administrar los objetos que no estoy usando. De hecho, en algún lugar que he leído, uno no debe hacer nada para recolectar basura, otros dicen que uno debe tener objetos del, mientras que otros explican que la eliminación de referencias de un objeto es suficiente para que Python lo recoja como basura.¿Cómo asignar objetos a la recolección de basura de python?

Por lo tanto, a riesgo de crear un duplicado, haré la pregunta nuevamente, pero de manera diferente, con la esperanza de obtener información más completa y clara.

En mi caso, quiero hacer una pequeña simulación con objetos que representen personas. Se crearán varias instancias de la clase Person(). Debería existir durante un tiempo hasta que prácticamente "muera" mientras se crearán otras instancias.

Ahora, ¿cómo puedo hacer que esta instancia Person() "muera" (suponiendo que muchas de estas instancias se crearán y no quiero que estas instancias cuelguen como fantasmas)?

Hay varias maneras que pueden hacer referencia a un objeto:

john = Person('john') 

o

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

o

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

¿Cuál es la mejor manera de mantener mi programa de limpieza, liberación de recursos ¿óptimo? ¿Y cuál es la mejor manera de hacer referencia a mi objeto para poder controlar la eliminación del objeto?

+0

Compruebe el módulo gc: http://docs.python.org/library/gc.html – rubik

+1

La respuesta corta es: usted no. Se lo lleva solo cuando no usas (tienes una referencia) más. O tal vez más tarde o nunca. GC no es determinista, la única garantía es que no se quedará sin memoria si hay basura para reutilizar (excepto en algunas circunstancias con GC conservadores, pero ni Python ni en ningún otro lenguaje administrado por memoria tiene que usar estos; los lenguajes con aritmética de puntero o una manera para que los punteros escapen como enteros, etc.). Y a menos que lo comprenda y por qué no necesita preocuparse en absoluto, debe dejarlo así. – delnan

+0

Esta pregunta podría aplicarse igualmente a ruby, Smalltalk, Java, C# o VB6 y quizás a muchos otros. – quamrana

Respuesta

4

Encuentro que la mayoría de los programas crean y eliminan objetos de forma muy natural, por lo que normalmente nunca me preocupo por ello.

Algunos ejemplos:

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. 

lo que supongo que está después es la siguiente:

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

def removePerson(personName): 
    del people[personName] 

removePerson('john') 

En este caso people es la lista maestra y se puede controlar cuando un Person se agrega y se retira de la lista (es un diccionario).

Puede que tenga que pensar en el concepto de una persona que se está creando y luego morir muy a fondo: una vez creada, ¿cómo interactúa la persona con la simulación? Al morir, ¿cómo deberías desenredar las referencias? (Está bien que una persona se refiera a otras cosas, como en el ejemplo House que mantendría a una persona con vida. Podría tener otros objetos aferrados únicamente al nombre de la persona).

+0

Gracias por este :) – Benjamin

7

Nada de esto realmente tiene algo que ver con la recolección de basura.

El método principal de administración de memoria de Python usa recuento de referencias.

En todos los casos anteriores, Python lleva un recuento de todas las referencias al objeto, y cuando no queda ninguno, el objeto se elimina (similar a std::shared_pointer en C++).

Referencias consiguen disminuyeron cuando

  1. el objeto llevando a cabo ellos es ya sea explícitamente suprimido (a través de del)
  2. o se va fuera de alcance (see also here (esp. ex. 8)).

En su caso, esto se aplica al objeto john, o cualquiera de los contenedores people. Saldrán del alcance al final de la función que los creó (suponiendo que no estén return ed a la función de llamada). La gran mayoría de las veces, puede dejarlos fuera del alcance: solo cuando crea objetos o colecciones realmente pesados, por ejemplo dentro de un ciclo grande, es posible que desee considerar utilizar del explícitamente.

La recolección de basura realmente sólo entra en juego cuando hay ciclos de referencia - por ejemplo, cuando un objeto se refiere a sí mismo. Me gusta:

a = [] 
a.append(a) 

De nuevo, esto sucede automáticamente, y no debería necesitar hacer nada especial.

+0

Gracias :) todas las respuestas fueron realmente buenas, recogí Quamrana porque dio una respuesta que era más consistente con el ejemplo de la pregunta. – Benjamin

9

Tal vez esto también puede ayudar:

>>> # 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 method; gc module; weakref module

+0

Gracias :) todas las respuestas fueron realmente buenas, recogí Quamrana porque dio una respuesta que era más consistente con el ejemplo de la pregunta. – Benjamin

+0

@Benjamin: Me alegro de que tengas tu respuesta :) – mouad

Cuestiones relacionadas