Circular reference problem -- advice?

Sean Blakey sblakey at freei.net
Mon Jul 10 15:35:59 EDT 2000


On Mon, Jul 10, 2000 at 12:06:46PM -0700, Erik Max Francis 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.
> -- 
> http://www.python.org/mailman/listinfo/python-list

Is dispatch the only thing you need self.map for?  If so, I think the easiest
way around this circular reference may be to reimplement dispatch do that
self.map is unneeded.  For example:
    def dispatch(self, name):
        getattr(self, name)()

Also, your self.map looks like it duplicates the information in the builtin
self.__dict__.  Parhaps you could use that instead?
    def dispatch(self, name):
        self.__dict__[name]()

Either of these solutions will allow you to remove the self.map completely.
    -Sean
-- 
Sean Blakey, sblakey at freei.com
Software Developer, FreeInternet.com
(253)796-6500x1025
"From there to here, from here to there, funny things are everywhere."
-- Dr. Seuss




More information about the Python-list mailing list