38 votes

Y a-t-il une différence entre [] et list() lors de l'utilisation de id() ?

Quelqu'un peut-il expliquer ce qui suit ?

Pourquoi l'identifiant est le même, mais les listes sont différentes ?

>>> [] is []
False
>>> id([]) == id([])
True

Y a-t-il une différence dans la création des listes ?

>>> id(list()) == id(list())
False
>>> id([]) == id([])
True

Pourquoi cela se produit-il ? Je reçois deux listes différentes. Pourquoi pas une seule, ou trois ou plus ?

>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868128>
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868170>
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868128>
>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x7fd2be868170>

75voto

Martijn Pieters Points 271458

Vous avez utilisé id() mauvais. id([]) prend l'identifiant mémoire d'un objet qui est jeté immédiatement . Après tout, plus rien ne s'y réfère une fois id() en a fini avec elle. Donc la prochaine fois que vous utiliserez id([]) Python y voit une opportunité de réutiliser la mémoire et, ô surprise, ces adresses sont bien les mêmes.

Cependant, il s'agit d'un détail d'implémentation, sur lequel vous ne pouvez pas compter, et il ne sera pas toujours possible de réutiliser l'adresse mémoire.

Notez que id() les valeurs sont uniquement uniques pendant toute la durée de vie de l'objet , voir le documentation :

Il s'agit d'un nombre entier qui est garanti unique et constant pour cet objet pendant sa durée de vie. Deux objets dont les durées de vie ne se chevauchent pas peuvent avoir la même valeur. id() valeur.

(C'est moi qui souligne en gras).

Ce id(list()) ne peut pas réutiliser l'emplacement mémoire est probablement dû aux mutations supplémentaires du tas causées par le fait de pousser la trame actuelle sur la pile pour appeler une fonction, puis de la sortir à nouveau lorsque la fonction list() l'appel revient.

Les deux sites [] y list() produire un nouveau objet liste vide ; mais vous devez d'abord créer des références à ces listes séparées (ici a y b ) :

>>> a, b = [], []
>>> a is b
False
>>> id(a) == id(b)
False
>>> a, b = list(), list()
>>> a is b
False
>>> id(a) == id(b)
False

La même chose se produit lorsque vous avez utilisé [].__repr__ . L'interpréteur interactif Python a un nom global spécial, _ que vous pouvez utiliser pour faire référence au dernier résultat produit :

>>> [].__repr__
<method-wrapper '__repr__' of list object at 0x10e011608>
>>> _
<method-wrapper '__repr__' of list object at 0x10e011608>

Cela crée une référence supplémentaire, donc le __repr__ et, par extension, la liste vide que vous avez créée pour elle, sont toujours considérés comme actifs . L'emplacement mémoire n'est pas libéré et n'est pas disponible pour la prochaine liste que vous créez.

Mais l'exécution [].__repr__ à nouveau, Python lie maintenant _ à ce nouvel objet méthode. Tout à coup, le précédent __repr__ n'est plus référencée par quoi que ce soit et peut être libérée, tout comme l'objet liste.

La troisième fois que vous exécutez [].__repr__ le premier emplacement mémoire est à nouveau disponible pour être réutilisé, c'est ce que fait Python :

>>> [].__repr__  # create a new method
<method-wrapper '__repr__' of list object at 0x10e00cb08>
>>> _            # now _ points to the new method
<method-wrapper '__repr__' of list object at 0x10e00cb08>
>>> [].__repr__  # so the old address can be reused
<method-wrapper '__repr__' of list object at 0x10e011608>

Vous ne créez jamais plus de deux listes ; la précédente (toujours référencée par _ ) et celui en cours. Si vous voulez voir plus d'emplacements mémoire, utilisez des variables pour ajouter une autre référence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X