2011-11-20 5 views
5
class ToBeDeleted: 
    def __init__(self, value): 
     self.value = val 

    # Whatever... 

    def __del__(self): 
     print self.value 

l = [ToBeDeleted(i) for i in range(3)] 
del l 

Imprime 2, 1, 0.Appel de 'del' sur une liste


  • Maintenant, est l'ordre des éléments supprimés défini quelque part dans la spécification ou est-il spécifique à la mise en œuvre? (ou peut-être que je ne comprends pas les mécanismes sous-jacents)

  • la sortie pourrait, par exemple, être 0, 1, 2? Je réalise que l'ordre 2, 1, 0 est probablement fait pour éviter les réaffectations de mémoire pour les éléments lors de leur suppression, mais la question demeure.

  • Et le dernier - quelle est la différence entre les instructions del l et del l[:]?

+3

doute fort que l'ordre des appels à __ 'de __del()' est spécifié nulle part. Ne pensez même pas à essayer d'écrire du code qui repose sur un ordre particulier. –

+0

Même si la commande a été spécifiée, vous pouvez conserver des références aux éléments de liste n'importe où, donc l'ordre dans lequel vos méthodes '__del__' sont appelées sera différent de l'ordre dans lequel les références sont supprimées de la liste. – millimoose

Répondre

8

Exécution del l supprimera toute référence à la liste, le symbole l sera parti. En revanche, l'exécution del l[:] supprime le contenu de la liste, laissant l comme une liste vide.

La méthode __del__ est ce qui s'exécute lorsque la dernière référence à une instance est en cours de destruction.

L'ordre de suppression n'est pas spécifié et est spécifique à l'implémentation. Lorsque vous exécutez del l, la seule chose qui est garantie est que le nombre de références pour la liste l et chacun de ses éléments va diminuer d'une unité.

Avec pypy, rien d'autre ne se produira tant que le garbage collector ne sera pas exécuté. L'ordre de suppression des objets dépend de l'ordre dans lequel GC visite les objets.

En cpython, l'OP a observé correctement que la décrémentation de référence se produit de droite à gauche. Lorsque vous appelez del l[:], voici le code utilisé pour décrémenter les refcounts: http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l700. Lorsque del l est invoqué, un code similaire est utilisé pour décrémenter les refcounts: http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l596

+1

Merci. Mais qu'en est-il de l'ordre des éléments supprimés? –

1
  • ordre de suppression est spécifique à la mise en œuvre.
  • Par la réponse au premier point, oui il pourrait le supprimer dans un autre ordre (même les éléments d'abord, aléatoire, peu importe), et éviter les réaffectations a peu à voir avec cela. C'est juste une question de comment la mise en œuvre choisit de marcher les enfants. Peut-être que l'allocateur de mémoire est plus heureux si l'ordre de libération inverse l'ordre d'allocation; mais c'est juste une supposition.
  • del l supprime la variable elle-même (et donc la liste, si rien d'autre ne la contient), tandis que del l[:] supprime tous les éléments de la liste. Essayez del l; print l.
2

D'autres ont déjà répondu. Je vais juste ajouter ce que j'ai trouvé dans les sources de CPython.

La fonction list_dealloc dans le fichier listobject.c contient ce commentaire immédiatement avant le bouclage sur les éléments de la liste pour décrémenter leurs comptes de référence:

/* Do it backwards, for Christian Tismer. 
     There's a simple test case where somehow this reduces 
     thrashing when a *very* large list is created and 
     immediately deleted. */ 
+0

Grande trouvaille! Ceci est également une preuve assez forte que l'ordre de suppression n'est pas spécifié et pourrait ne jamais l'être. – millimoose

Questions connexes