Deleting objects with method reference

M

Martin

I can't delete this object after I call the Set() function.

Why is this so special, and are there any way around it besides removing the ref ?

class B:
def __del__(self):
print "del"
def F(self):
print "f"
def Set(self):
self.v = self.F


o1 = B()
o1.Set()
del o1


o2 = B()
o2.Set()
o2.v = None
del o2

-Martin
 
P

Peter Otten

Martin said:
I can't delete this object after I call the Set() function.

Why is this so special, and are there any way around it besides removing
the ref ?

class B:
def __del__(self):
print "del"
def F(self):
print "f"
def Set(self):
self.v = self.F


o1 = B()
o1.Set()
del o1


o2 = B()
o2.Set()
o2.v = None
del o2

self.F consists of a function and an instance reference, so you are
introducing a cycle with o1 referring self.F and self.F referring to o1.
Cycles can only be garbage-collected if the objects involved do not have a
__del__() method. In your example o1 would be collected if you weren't
looking, i. e. B wouldn't attempt to trace the deletion with __del__().
See http://www.python.org/doc/current/lib/module-gc.html, especially the
"garbage" section for details.

You can verify this with a weakref.ref object with an appropriate callback:

import weakref
def ondel(o):
print "del"

class B:
def F(self):
print "f"
def Set(self):
self.v = self.F


o1 = B()
o1.Set()
w = weakref.ref(o1, ondel)
del o1

Peter
 
M

Martin

Peter Otten said:
...
You can verify this with a weakref.ref object with an appropriate callback:

import weakref
def ondel(o):
print "del"

class B:
def F(self):
print "f"
def Set(self):
self.v = self.F


o1 = B()
o1.Set()
w = weakref.ref(o1, ondel)
del o1

Peter

Hi Peter and thanks for your reply!

However your example doesn't seem to work.

import weakref
import gc

def ondel(o):
print "del"

class B:
def F(self):
print "f"
def Set(self):
self.v = self.F

o1 = B()
w1 = weakref.ref(o1, ondel)
del o1
o2 = B()
o2.Set()
w2 = weakref.ref(o2, ondel)
del o2

When I delete o2 I get no output. And gc.garbage is still empty!

gc.garbage

I have tried it in both python 2.1 and 2.3.3. Why doesn't it work?

-Martin
 
J

Jeff Epler

It works here when I call gc.collect(). There's not exactly a guarantee
about when garbage will be collected otherwise.del
3

Jeff
 
P

Peter Otten

Martin said:
However your example doesn't seem to work.

import weakref
import gc

def ondel(o):
print "del"

class B:
def F(self):
print "f"
def Set(self):
self.v = self.F

o1 = B()
w1 = weakref.ref(o1, ondel)
del o1
o2 = B()
o2.Set()
w2 = weakref.ref(o2, ondel)
del o2

When I delete o2 I get no output. And gc.garbage is still empty!

gc.garbage

I have tried it in both python 2.1 and 2.3.3. Why doesn't it work?

I've cut and pasted the above, put it into ondel.py,
removed added
print gc.garbage
as the last line and executed it (on Linux). Here's what I got:

$ python2.1 ondel.py
del
[]
$ python2.2 ondel.py
del
[]
$ python2.3 ondel.py
del
[]
del
$

So at least with python 2.3.3 ondel() is called for both objects. The order
however suggests interference with the shutdown process. Adding
gc.collect()
before
print gc.garbage
this changes to

$ python2.3 ondel.py
del
del
[]
$ python2.2 ondel.py
del
del
[]
$ python2.1 ondel.py
del
del
[]

which I would have expected in the first place. So why does(n't) it work
that way? I have no idea, but explicitly invoking the garbage collector
does definitely not seem the way to go.

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top