Si un dictionnaire contient des objets modifiables ou des objets de classes personnalisées (par exemple un ensemble de requêtes, ou même un DateTime), l'appel de clear()
sur le dictionnaire supprimera-t-il ces objets de la mémoire? Se comporte-t-il différemment que de parcourir le dict et de del
les supprimer?
par exemple. considérer
class MyClass(object):
'''Test Class.'''
my_obj_1 = MyClass()
my_obj_2 = MyClass()
my_dict = { 'foo' : my_obj_1, 'bar' : my_obj_2 }
alors c'est
my_dict.clear()
pareil que
for key in my_dict.keys():
del my_dict[key]
?
documentation Python sur les dict indique que del d[key]
Supprime d[key]
Du dictionnaire tandis que d.clear()
supprime chaque clé, donc fondamentalement leur comportement est le même.
Sur le problème de mémoire, dans Python lorsque vous "supprimez", vous supprimez essentiellement une référence à un objet. Lorsqu'un objet n'est référencé par aucune variable ni aucun autre objet ou devient inaccessible, il devient ordures et peut être supprimé de la mémoire. Python a un garbage collector qui de temps en temps il fait ce travail pour vérifier quels objets sont des ordures et libère la mémoire qui leur est allouée. Si l'objet que vous supprimez du dictionnaire est référencé par une autre variable alors il est toujours accessible, donc ce n'est pas des ordures donc il a gagné " t être supprimé. Je vous laisse ici quelques liens si vous êtes intéressé à lire sur la collecte des ordures en général et la collecte des ordures de python en particulier.
Il y a en fait une très petite différence entre les deux. clear()
libérera la mémoire du hashset utilisé dans le dict, tandis que le retrait de la clé ne le sera pas.
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
Se comporte-t-il différemment que de parcourir le dict et de
del
les supprimer?
Il convient de noter ici que toute classe personnalisée implémentant la classe de base abstraite MutableMapping
obtient clear()
comme méthode de mixage "gratuite".
Les seules méthodes que vous devez remplacer pour instancier une sous-classe MutableMapping
sont:
__getitem__, __setitem__, __delitem__, __iter__, __len__
Comme vous pouvez stocker les données dans votre classe de mappage comme vous le souhaitez, la seule façon dont clear()
peut comprendre comment effacer réellement vos données consiste à utiliser une ou plusieurs de ces cinq méthodes. Maintenant, vous pourriez avoir une idée des méthodes que clear()
utilise, mais pourquoi deviner quand nous pouvons expérimenter?
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())
En utilisant la classe définie ci-dessus, il est facile de voir comment clear()
est implémenté:
>>> 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 d'autres termes, la méthode mixin clear()
est fondamentalement implémentée comme for key in self: del self[key]
.
Désormais, un avertissement: les types intégrés tels que dict
sont implémentés en C, donc la méthode dict.clear
Peut ne pas être littéralement identique à for key in mydict: del mydict[key]
. Je m'attendrais à une optimisation dans les coulisses, peut-être une stratégie complètement différente - mais j'espère que cet exemple vous donne une idée de la façon dont vous pourriez attendre une méthode clear()
pour travailler en Python.
C'est la même chose que d'appeler del d['foo']
- il supprime simplement les entrées, mais il n'affecte pas les clés ou les valeurs elles-mêmes.
Bien sûr, ils peuvent alors devenir poubelles s'il n'y a aucune autre référence à eux.
la commande del supprime la référence de l'élément particulier dans la liste, la commande clear efface toutes les paires de valeurs clés en une seule fois afin que la fonctionnalité soit la même, elles déréférencent et la tâche de repos de la supprimer de la mémoire est effectuée par le garbage collector
Dans votre cas, les deux objets MyClass
sont partagés. Ils seront toujours accessibles via le my_obj_1
et my_obj_2
.
Avez-vous même essayé d'exécuter le code? Le code suivant avec Python 3.7 lève une exception! "RuntimeError: le dictionnaire a changé de taille pendant l'itération":
for key in my_dict.keys():
del my_dict[key]
Toutes les réponses précédentes sont bonnes. Je voulais juste ajouter quelques points supplémentaires sur les différences de del et clear:
De plus, vous avez déclaré deux variables my_obj_1 et my_obj_2; Même si vous supprimez/effacez my_dict, ces deux variables contiennent des références aux objets MyClass et ne disparaîtront pas tant que my_obj_1 et my_obj_2 ne seront pas hors de portée; donc, si les objets MyClass contiennent de la mémoire (disons une liste ou quelque chose), alors si votre intention est de libérer la mémoire en supprimant/effaçant my_dict, cela ne se produit pas!
class MyClass (object): '' 'Test Class.' ''
my_obj_1 = MyClass () my_obj_2 = MyClass ()