2016-02-03 10 views

Antwort

14

Python wieder verwendet den gleichen Speicherplatz wie Sie keine anderen Verweise auf die Objekte halten, sobald id(a.f) ausgewertet wird mehr Verweise auf das Objekt sind, so dass es gc'd wird dann den gleichen Speicherplatz Python ist frei wiederzuverwenden für a.g. wenn Sie die Methoden Namen zuweisen werden Sie ein anderes Verhalten sehen:

# creates a reference to the method f 
In [190]: f = a.f 
# creates a reference to the method g 
In [191]: g = a.g 
# cannot reuse the memory location of f as it is still referenced 
In [192]: id(f) == id(g) 
Out[192]: False 

Sie eigentlich wirklich nur speichern, müssen Sie einen Verweis auf f wie oben das gleiche Verhalten zu sehen.

In [201]: f = a.f 

In [202]: id(f) == id(a.g) 
Out[202]: False 

können Sie den Referenzzähler sehen mit sys.getrefcount oder gc.gc.get_referrers:

In [2]: import gc 

In [3]: f = a.f 

In [4]: len(gc.get_referrers(a.g)),len(gc.get_referrers(f)) 
Out[4]: (0, 1) 

In [5]: sys.getrefcount(a.g),sys.getrefcount(f) 
Out[5]: (1, 2) 

Der einzige Grund, warum Sie 1 für ag sehen, weil Die Zahl zurückgegeben wird, ist im Allgemeinen eine höhere als man erwarten könnte, weil es enthält den (temporären) Verweis als Argument für getrefcount(). Es ist analog zu Ihrem eigenen Beispiel, nachdem die Methode ausgewertet wird Sie immer noch einen Verweis auf f haben, mit a.g wäre der Refcount 0, so dass es sofort Müll gesammelt und Python ist frei, den Speicherort für alles andere zu verwenden .

Es ist auch erwähnenswert, dass das Verhalten nicht auf Verfahren beschränkt ist, sondern es ist nur ein CPython Implementierungsdetail und nicht etwas, das Sie jemals verlassen sollen:

In [67]: id([]), id([]) 
Out[67]: (139746946179848, 139746946179848) 

In [73]: id(tuple()),id([]),id([]) 
Out[73]: (139747414818888, 139746946217544, 139746946217544) 

In [74]: id([]),id([]),id([]) 
Out[74]: (139746946182024, 139746946182024, 139746946182024) 

In [75]: id([]),id(tuple()),id([]) 
Out[75]: (139746946186888, 139747414818888, 139746946186888) 

In [76]: id(tuple()),id([]),id(tuple()) 
Out[76]: (139747414818888, 139746946217736, 139747414818888) 
+0

Es ist mein Verständnis, das leere Tupel ist ein Singleton (Implementierung Detail). Das ist also für mich nicht so interessant wie das leere Listenbeispiel. –

4

Samt Speicher Standort verwendet werden von Python für Methoden a.f und a.g, die sind ** zwei Objekte mit nicht überlappenden Lebenszeiten *, so id gibt die gleiche Identität für beide zurück, siehe detailliertere Erklärungen unten.

Aus der Dokumentation für die is operator:

Die Betreiber ist und testen Sie ist nicht für die Objektidentität: x y wahr ist , wenn und nur wenn x und y das gleiche Objekt sind.

Aus der Dokumentation für die ist id

Rückkehr der „Identität“ eines Objekts. Dies ist eine ganze Zahl (oder lange ganze Zahl), die für dieses einzigartigen und konstant sein Objekt garantiert während seiner Lebensdauer. Zwei Objekte mit nicht überlappenden Lebensdauern können denselben ID() -Wert haben.

Erläuterungen: Jedes Mal, wenn Sie eine Methode über class.name oder instance.name nachzuschlagen, wird das Verfahren Objekt eine neue erstellt. Python verwendet die descriptor protocol, um die Funktion jedes Mal in ein Methodenobjekt einzufügen.Wenn Sie id(a.f) oder id(a.g) nachschlagen, wird ein neues Methodenobjekt erstellt.

  1. Wenn Sie ID a.f grubben, wird eine Kopie davon im Speicher erstellt. Dieser Speicherplatz von id
  2. zurückgegeben Da es keine Hinweise auf die neu geschaffenen Verfahren sind, ist es von der GC zurückgewonnen (jetzt verfügbar Speicheradresse wieder)
  3. Nachdem Sie id von a.g, eine Kopie davon bekommen wird in der gleichen Speicheradresse angelegt, die Sie id wieder
  4. du hast truthy ids Vergleich

Gut Mangel retrieve mit!

2

a.f und A. G sind verschiedene Objekte.
ist Betreiber nur true zurück, wenn sie ein Objekt sind. aber zwei Objekte mit nicht-überlappenden Lebensdauern kann die gleiche ID() Wert haben.

siehe here für id Betreiber

2

Der Betreiber is prüft die Objektidentität nicht Wert, und in diesem Fall haben Sie zwei separate Funktion (Objekt) so sie andere Identität haben.

Und zu folgendem Teil:

>>> id(a.f) == id(a.g) 
True 

Da Python die Objekte zur Laufzeit ersten Mal Python versucht, die ID von a.f die a.g ist bereits auf Python-Wiki nicht zu bekommen erstellt definiert und basiert Zwei Objekte mit nicht überlappenden Lebensdauern können denselben id() -Wert haben. so in diesem Fall Objekte a.f und a.g, die nicht überlappenden Lebensdauern aufweisen muss gleich id.

Geben Sie die "Identität" eines Objekts zurück. Dies ist eine ganze Zahl (oder lange ganze Zahl), die für dieses einzigartigen und konstant sein Objekt garantiert während seiner Lebensdauer. Zwei Objekte mit nicht-überlappenden Lebensdauern können haben die gleiche ID() Wert.

Einige zusätzliche Notizen zu is Betreiber:

Wie gesagt in der oben erwähnten Linien der Bediener überprüft die Identität von Objekten und Objekt in Python zur Laufzeit erstellt werden soll. Aber das ist nicht wahr für einige kleine Typen wie ganze Zahlen und Strings, weil dein singletones sind und nicht die Python-Objekte. Daher wird der Speicher wie C-Typen sofort im Speicher abgelegt.

Zur besseren Demonstration können Sie die folgenden Beispiele sehen:

>>> 100 is 10*10 
True 
>>> 
>>> 1000 is 10*100 
False 
>>> 

Und für Strings:

>>> 'aaaa'*5 is 'a'*20 
True 
>>> 'aaaa'*50 is 'a'*200 
False 
Verwandte Themen