coder21
coder21

Reputation: 129

Python release memory when changing member of a object within the class

I have been playing around with Python objects in IDLE and observed that if a member variable of an object is changed, the memory isn't released! Here is an example:

import weakref
import gc

class subclass():
    def __init__(self, data):
         self.data=data
    def __repr__(self):
    return self.data.__str__()

class newclass():
    def __init__(self,data):
         self.data=subclass(data)
    def test(self):
         refs=weakref.ref(self.data)()
         self.data=None
         gc.collect()
         print ("ref", refs)

a = newclass(data=3)
a.test()
print ("val", a.data)

The output of this code, I would expect to be:

ref None
val None

It turns out that the ref, however, is still a valid reference and the output is:

ref 3
val None

I would like to see that memory being released. I would like to understand how.

Upvotes: 0

Views: 88

Answers (1)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160447

You've misunderstood something crucial, unfortunately. When you call the weakref object returned from weakref.ref you get back the original object. Try printing type(ref) and see how <class '__main__.subclass'> is returned. See the docs on weakref.ref:

The original object can be retrieved by calling the reference object if the referent is still alive; if the referent is no longer alive, calling the reference object will cause None to be returned.

(Emphasis mine)

You called the reference object and got your class subclass back; a reference to it therefore still exists in ref not allowing it to get garbage-collected.

If you don't call it, on the other hand, you'll notice how the line print('ref', refs) indicates that the reference is dead:

ref <weakref at 0x7f3028188a48; dead>
val None

i.e as the sole reference to your object and due to the fact it is weak, it got collected.

As an aside, if you want to be portable between Python 2 and 3 you'll want your classes to subclass from object and not use empty parentheses (). If you don't care about portability, the parentheses can be dropped without change in semantics. :-)

Upvotes: 3

Related Questions