Circular reference problem -- advice?

shindich at my-deja.com shindich at my-deja.com
Mon Jul 10 20:57:57 EDT 2000


In article <396A1EC6.6738CFCC at alcyone.com>,
  Erik Max Francis <max at alcyone.com> wrote:
> I'm fairly new to Python, although it's simple enough that I've
already
> been able to write some fairly involved programs in it (I already know
> C, C++, Perl, etc.).  This question isn't so much about what's going
> wrong, but rather what's the best, most natural way to get around it.
>
> I've come across a problem due to circular references, and I'm not
sure
> what's the best way to tackle it.  In essence, the problem is that I
> need a particular class to keep an associative array of its methods
for
> a lookup table (it's essentially a dispatcher).  But with references
to
> its own bound methods, Python's garbage collector concludes it has
> circular references and thus its destructor never gets called.
>
> Here is a simplified standalone program that demonstrates what I'm
> talking about:
>
> class C:
>     def __init__(self):
>         print "in constructor"
>         self.map = { 'f': self.f, 'g': self.g }
>
>     def __del__(self):
>         print "in destructor"
>
>     def f(self):
>         print "in C.f"
>
>     def g(self):
>         print "in C.g"
>
>     def dispatch(self, name):
>         self.map[name]()
>
> c = C()
> c.dispatch('f')
>
> When run, this program prints
>
>     max at charmaine:~/tmp% ./circ.py
>     in constructor
>     in C.f
>
> and that's it; because of the circular reference, the destructor never
> gets called.
>
> For the application I need, it's imperative that the destructor get
> called.  What is the best way to solve this?  I can think of a few:
>
> - Move the map to a local variable in the dispatching function
> - Make map a lookup table of _unbound_ methods
> - Build a string of the function call and then exec it
>
> What would be the most effective way of getting around this?  I'm
> thinking that using unbound methods would probably be the best way.
>
> --
>  Erik Max Francis / max at alcyone.com / http://www.alcyone.com/max/
>  __ San Jose, CA, US / 37 20 N 121 53 W / ICQ16063900 / &tSftDotIotE
> /  \ We'll have to make our own luck from now on.
> \__/ Louis Wu
>     Computer science / http://www.alcyone.com/max/reference/compsci/
>  A computer science reference.
>
Hmm...
It seems to me that there is no need to have this map at all.
Python is an introspective language, so you can easily discover object's
properties at run time by name. Here is my version of your program:

#!/usr/bin/python

class C:
    def __init__(self):
        print "in constructor"

    def __del__(self):
        print "in destructor"

    def f(self):
        print "in C.f"

    def g(self):
        print "in C.g"

    def dispatch(self, name):
        func = getattr (self, name)
        apply (func, [])


c = C()
c.dispatch('f')

This is the output:
>>>in constructor
>>>in C.f
>>>in destructor

I hope this helps!

Alex Shindich
http://www.shindich.com/


Sent via Deja.com http://www.deja.com/
Before you buy.



More information about the Python-list mailing list