2012-05-04 22 views
22

Si un diccionario contiene objetos mutables u objetos de clases personalizadas (por ejemplo, un conjunto de consultas, o incluso un DateTime), entonces se llamará a clear() en el diccionario para eliminar estos objetos de la memoria? ¿Se comporta de forma diferente a un bucle a través del dict y del?¿El método clear() del diccionario elimina todos los objetos relacionados con los elementos de la memoria?

por ejemplo. consideran

class MyClass(object): 
    '''Test Class.''' 

my_obj_1 = MyClass() 
my_obj_2 = MyClass() 

my_dict = { 'foo' : my_obj_1, 'bar' : my_obj_2 } 

entonces es

my_dict.clear() 

mismo que

for key in my_dict.keys(): 
    del my_dict[key] 

?

Respuesta

36

Python documentation on dicts establece que del d[key] elimina d[key] del diccionario mientras d.clear() elimina todas las claves, así que básicamente su comportamiento es el mismo.

En la cuestión de la memoria, en Python cuando "borra" está básicamente eliminando una referencia a un objeto. Cuando un objeto no es referenciado por ninguna variable u otro objeto o se vuelve inalcanzable, se convierte en basura y se puede eliminar de la memoria. Python tiene un recolector de basura que de vez en cuando hace este trabajo de verificar qué objetos son basura y libera la memoria asignada para ellos. Si el objeto que está eliminando del diccionario está referenciado por otra variable, entonces todavía es alcanzable, por lo tanto, no es basura, por lo que no se eliminará. Te dejo aquí algunos enlaces si estás interesado en leer sobre la recolección de basura en general y sobre la recolección de basura de Python en particular.

3

Es lo mismo que llamar al del d['foo'] - simplemente borra las entradas, pero no afecta a las claves ni a los valores mismos.

Por supuesto, pueden convertirse en basura coleccionable si no hay otras referencias a ellos.

+2

En otras palabras, si se comparten o las llaves o los valores (asignado a otra variable), no se eliminarán los objetos ni por 'd.clear()', ni por 'del d [ clave] '. Un diccionario almacena referencias a claves y valores. * Las referencias borran * las operaciones. – pepr

+0

@pepr Eso es correcto. – Marcin

+0

Sí, entonces la clave que me faltaba aquí es borrar la operación, solo borra la referencia, la limpieza de memoria es manejada por el recolector de basura – 0xc0de

1

En su caso, se comparten los dos objetos MyClass. Todavía estarán accesibles a través del my_obj_1 y my_obj_2.

5

¿Se comportan de manera diferente que un bucle a través de la dict y del eting ellos?

Vale la pena señalar aquí que cualquier clase personalizada implementación de la clase base abstracta MutableMappingclear() obtiene como un método mixin "libre".

Los únicos métodos que necesita para anular el fin de crear una instancia de una subclase MutableMapping son:

__getitem__, __setitem__, __delitem__, __iter__, __len__ 

Ya que se puede almacenar los datos en su clase de mapeo lo que le gusta, la única manera clear() puede encontrar la manera para borrar sus datos es usando uno o más de esos cinco métodos. Ahora, puede adivinar qué métodos está usando clear(), pero ¿por qué adivinar cuándo podemos experimentar?

import collections 

class MyMap(collections.MutableMapping): 
    def __init__(self, mydict): 
     self._top_secret_data = mydict 

    def __getitem__(self, key): 
     print 'getitem' 
     return self._top_secret_data[key] 

    def __setitem__(self, key, value): 
     raise Exception('where did you want that?') 

    def __len__(self): 
     raise Exception('a gentleman never tells') 

    def __delitem__(self, key): 
     print '[shredding intensifies]' 
     del self._top_secret_data[key] 

    def __iter__(self): 
     def keygen(): 
      for key in self._top_secret_data: 
       print 'faster! faster!' 
       yield key 
     return iter(keygen()) 

Utilización de la clase definida anteriormente, es fácil ver cómo se implementa clear():

>>> m = MyMap({1:'a', 2:'b', 3:'c'}) 
>>> m.clear() 
faster! faster! 
getitem 
[shredding intensifies] 
faster! faster! 
getitem 
[shredding intensifies] 
faster! faster! 
getitem 
[shredding intensifies] 
>>> 

En otras palabras, el método mixin clear() se implementa básicamente como for key in self: del self[key].

Ahora, un descargo de responsabilidad: incorporado en tipos tales como dict se implementan en C, por lo que el método dict.clear puede no ser literalmente idéntica a for key in mydict: del mydict[key]. Yo esperaría alguna optimización detrás de las escenas, tal vez una estrategia completamente diferente - pero espero que este ejemplo le da una idea de cómo se puede esperar que clear() un método para trabajar en Python.

4

De hecho, hay una diferencia muy pequeña entre los dos. clear() liberará la memoria del hashset utilizado en el dict, mientras que quitar la clave no lo hará.

a = dict.fromkeys(range(1000)) 

In [10]: sys.getsizeof(a) 
Out[10]: 49432 

In [11]: a.clear() 

In [12]: sys.getsizeof(a) 
Out[12]: 280 

In [13]: a = dict.fromkeys(range(1000)) 

In [14]: for i in range(1000): 
    ....:  del a[i] 
    ....:  

In [15]: sys.getsizeof(a) 
Out[15]: 49432 
+0

¡sí! Encontré lo mismo, y es muy importante, cuando lidias con un dict muy grande. Nunca utilizaría un bucle 'for' para eliminar todas las claves, ya que simplemente no libera la memoria y, por lo tanto, no tiene sentido –

1

la del comando borrar la referencia del artículo en particular en la lista, los claros todos los pares de valores clave de mando clara en una van por lo que la funcionalidad es la misma que tanto eliminar la referencia y la tarea resto de la eliminación de la memoria es realizado por el recolector de basura

Cuestiones relacionadas