web-dev-qa-db-fra.com

Existe-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-il 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 d'une liste?

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

Pourquoi cela arrive-t-il? Je reçois deux listes différentes. Pourquoi pas seulement un 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>
38
Vlad Okrimenko

Vous avez mal utilisé id(). id([]) prend l'identifiant mémoire d'un objet qui est jeté immédiatement. Après tout, rien n'y fait référence une fois que id() en a fini. Ainsi, la prochaine fois que vous utiliserez id([]) Python voit une opportunité de réutiliser la mémoire et voilà, ces adresses sont en effet 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 en mesure de réutiliser l'adresse mémoire.

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

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

(Souligné par moi).

Cette id(list()) ne peut pas réutiliser l'emplacement mémoire est probablement due aux mutations de tas supplémentaires provoquées en poussant le cadre actuel sur la pile pour appeler une fonction, puis en la réécrivant lorsque la fonction list() retour d'appel.

[] Et list() produisent un nouvel objet de liste vide; mais vous devez d'abord créer des références à ces listes distinctes (ici a et 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 référencer le 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 la méthode __repr__ Et, par extension, la liste vide que vous avez créée pour elle, sont toujours considérées comme actives. L'emplacement mémoire n'est pas libéré et n'est pas disponible pour la prochaine liste que vous créez.

Mais en exécutant à nouveau [].__repr__, Python lie désormais _ À ce nouvel objet de méthode. Du coup, la méthode __repr__ Précédente n'est plus référencée par rien et peut être libéré, tout comme l'objet liste.

La troisième fois que vous exécutez [].__repr__, Le premier emplacement de mémoire est à nouveau disponible pour réutilisation, donc Python fait exactement cela:

>>> [].__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; le précédent (toujours référencé par _) et l'actuel. Si vous souhaitez voir plus d'emplacements de mémoire, utilisez des variables pour ajouter une autre référence.

76
Martijn Pieters