6

When is the below python static classs variable garbage collected? I was expecting to see the message from the static variable foo destructor.

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()

The output is (Python 2.7):

Foo init running
Bar init running
Destructor Bar

I was expecting:

Foo init running
Bar init running
Destructor Foo
Destructor Bar
4
  • Not a duplicate one to me. The other question is about circular references. Commented Oct 9, 2015 at 9:21
  • 2
    stackoverflow.com/questions/14628486/… Commented Oct 9, 2015 at 16:12
  • And what is a "Python static variable"? Does this concept exist? Commented Oct 9, 2015 at 16:13
  • It works in Python 3.4 Commented Oct 12, 2015 at 7:39

1 Answer 1

3

So we would expect the reference to the foo object to be deleted when the Bar class is deleted. And that is generally what happens. If you try

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

I get

Foo init running
Bar init running
Destructor Bar
Destructor Foo

and you can see both destructors called in both Python 2.7 and Python 3.4. However, in Python 2.7, Bar is not being properly destructed during program close down. As the docs say:

It is not guaranteed that del() methods are called for objects that still exist when the interpreter exits.

Why is Bar not destructed during interpreter exit?

It seems likely that the class in Python 2.7 is not destructed because of circular references (see below). In Python 3.4 (after PEP 442) objects with circular references are reliably destructed (even if they have __del__ methods) and this may explain the change.

However, this does not completely explain the difference because although the class is in a reference cycle, the class itself does not have a destructor.

It seems that in Python 2 objects with circular references are not reliably destructed during interpreter exit, whereas they are in Python 3.4. I give some more information here.

Edit (more detail about circular references):

Classes contain cyclic references back to themselves, firstly via their dictionary:

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

and secondly via their MRO details:

MyClass in MyClass.__mro__
Sign up to request clarification or add additional context in comments.

7 Comments

This does not explain why it's not deleted.
It is a feature of Python 2.7 but I don't fully understand the design rationale.
Hmm - more thought and I have come up with a plausible explanation
Can you explain where is the circular reference? Please elaborate a bit on your last paragraph. I don't fully understand it.
@A.P. Well I'm not sure - I got it from here. But I'm looking into it. Certainly all classes have a link to their Metaclass and some Metaclasses have links to classes but not sure if all do?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.