2016-11-26 1 views
38

Kann jemand folgendes erklären?Gibt es einen Unterschied zwischen [] und list() bei der Verwendung von id()?

Warum ist die ID gleich, aber die Listen sind unterschiedlich?

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

Gibt es einen Unterschied bei der Listenerstellung?

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

Warum passiert das? Ich bekomme zwei verschiedene Listen. Warum nicht nur eins, drei oder mehr?

>>> [].__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> 

Antwort

76

Sie haben id() falsch verwendet. id([]) übernimmt die Speicher-ID eines Objekts, das sofort verworfen wird. Immerhin referenziert nichts mehr, wenn fertig ist. Also das nächste Mal, wenn Sie id([]) verwenden Python sieht eine Gelegenheit, den Speicher wieder zu verwenden und siehe da, diese Adressen sind in der Tat gleich.

Dies ist jedoch ein Implementierungsdetail, auf das Sie sich nicht verlassen können, und es wird nicht immer in der Lage sein, die Speicheradresse wiederzuverwenden.

Beachten Sie, dass id() Werte für die Lebensdauer des Objekts nur einzigartig sind, sehen die documentation:

Dies ist eine ganze Zahl, die für dieses Objekt eindeutig und konstant ist während seiner gesamten Lebensdauer gewährleistet ist. Zwei Objekte mit nicht überlappenden Lebensdauern können den gleichen Wert haben id().

(Fett Hervorhebung meins).

id(list()) kann den Speicherort nicht wiederverwendet werden, wahrscheinlich aufgrund der zusätzlichen Heap-Mutationen verursacht durch Drücken des aktuellen Rahmens auf dem Stapel, um eine Funktion aufzurufen, dann erneut, wenn der list() Aufruf zurückgibt.

Beide und list() produzieren ein neues leeres Listenobjekt; aber Sie müssen zuerst Verweise auf diese separate Listen erstellen (hier a und 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 

Das gleiche passiert, wenn Sie [].__repr__ verwendet. Das interaktive Python-Interpreter hat einen speziellen globalen Namen, _, dass Sie das letzte Ergebnis erzeugte Referenz verwenden können:

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

, dass eine zusätzliche Referenz erzeugt, so dass die __repr__ Verfahren, und durch die Erweiterung, die leere Liste, die Sie erstellt dafür werden immer noch als aktiv betrachtet. Der Speicherort ist nicht freigegeben und nicht verfügbar für die nächste Liste, die Sie erstellen.

Bei der erneuten Ausführung von [].__repr__ bindet Python nun _ an das neue Methodenobjekt. Plötzlich wird die vorherige __repr__-Methode von nichts mehr referenziert und kann ebenso wie das Listenobjekt freigegeben werden.

Das dritte Mal, wenn Sie [].__repr__ den ersten Speicherplatz auszuführen ist wieder verfügbar für die Wiederverwendung, so Python macht genau das:

>>> [].__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> 

Sie nie mehr als zwei Listen erstellen; der vorherige (immer noch von _ referenziert) und der aktuelle. Wenn Sie mehr Speicherorte anzeigen möchten, verwenden Sie Variablen, um eine weitere Referenz hinzuzufügen.

Verwandte Themen