2015-10-09 21 views
6

Wann ist die folgende Python statische Klassen Variable Garbage gesammelt? Ich habe erwartet, die Nachricht von der statischen Variable Foo Destruktor zu sehen.Python statische Variable Freigabe

class Foo(object): 
    def __init__(self): 
     print "Foo init running" 

    def __del__(self): 
     print "Destructor Foo" 

class Bar(object): 
    foo = Foo() 
    def __init__(self): 
     print "Bar init running" 

    def __del__(self): 
     print "Destructor Bar" 

bar_obj = Bar() 

Der Ausgang ist (Python 2.7):

Foo init running 
Bar init running 
Destructor Bar 

Ich erwartete:

Foo init running 
Bar init running 
Destructor Foo 
Destructor Bar 
+0

Nicht ein Duplikat für mich. Die andere Frage betrifft "Zirkelbezüge". – luoluo

+2

https://stackoverflow.com/questions/14628486/why-arent-destructors-guaranteed-to-be-called-on-interpreter-exit –

+0

Und was ist eine "Python statische Variable"? Gibt es dieses Konzept? –

Antwort

3

So würden wir die Referenz auf das foo Objekt erwarten gelöscht werden, wenn die BarDie Klasse wird gelöscht. Und das passiert im Allgemeinen. Wenn Sie

class Foo(object): 
    def __init__(self): 
     print("Foo init running") 

    def __del__(self): 
     print("Destructor Foo") 

class Bar(object): 
    foo = Foo() 
    def __init__(self): 
     print("Bar init running") 

    def __del__(self): 
     print("Destructor Bar") 


def f(): 
    bar_obj = Bar() 

f() 
del Bar 

versuchen bekomme ich

Foo init running 
Bar init running 
Destructor Bar 
Destructor Foo 

und Sie können beide Destruktoren sowohl in Python 2.7 und Python 3.4 genannt sehen. In Python 2.7 wird jedoch Bar während des Schließens des Programms nicht ordnungsgemäß zerstört. Da die docs sagen:

Es ist nicht garantiert, dass del() Methoden für Objekte genannt werden, die nach wie vor, wenn der Dolmetscher Ausgänge vorhanden sind.

Warum wird Bar beim Beenden des Interpreters nicht zerstört?

Es scheint wahrscheinlich, dass die Klasse in Python 2.7 nicht wegen zirkulärer Referenzen zerstört wird (siehe unten). In Python 3.4 (nach PEP 442) werden Objekte mit Zirkelbezügen zuverlässig zerstört (selbst wenn sie __del__ Methoden haben) und dies könnte die Änderung erklären.

Dies erklärt jedoch nicht vollständig den Unterschied, da die Klasse selbst keinen Destruktor hat, obwohl sich die Klasse in einem Referenzzyklus befindet.

Es scheint, dass in Python 2 Objekte mit Zirkelverweisen beim Interpreter-Exit nicht zuverlässig zerstört werden, während sie in Python 3.4 sind. Ich gebe weitere Informationen here.

Edit (mehr Details über zirkuläre Referenzen):

Klassen enthalten zyklische Verweise auf sich selbst zurück, zunächst über ihre Wörterbuch:

MyClass.__dict__['__dict__'].__objclass__ == MyClass 

und andererseits über ihre MRO Details:

MyClass in MyClass.__mro__ 
+0

Dies erklärt nicht, warum es nicht gelöscht wird. – luoluo

+0

Es ist eine Funktion von Python 2.7, aber ich verstehe die Designprinzipien nicht vollständig. – strubbly

+0

Hmm - mehr gedacht und ich habe eine plausible Erklärung – strubbly