python bijection

Joshua Bronson jabronson at gmail.com
Sat Nov 28 04:30:44 EST 2009


On Nov 27, 9:36 pm, "Gabriel Genellina" <gagsl-py2 at yahoo.com.ar>
wrote:
> En Fri, 27 Nov 2009 15:12:36 -0300, Francis Carr <coldtortuga at gmail.com>  
> escribió:
>
> > I was really inspired by this discussion thread! :-)
>
> > After much tinkering, I think I have a simpler solution.  Just make
> > the inverse mapping accessible via an attribute, -AND- bind the
> > inverse of -THAT- mapping back to the original.  The result is a
> > python dict with NO NEW METHODS except this inverse-mapping
> > attribute.  I have posted it on code.activestate.com as <a
> > href="http://code.activestate.com/recipes/576968/">Recipe 576968:
> > Flipdict -- python dict that also maintains a one-to-one inverse
> > mapping</a>
>
> Nice idea!

Indeed! Thanks for sharing! I liked this so much I added something
similar in http://bitbucket.org/jab/toys/src/tip/bidict.py (I made the
inverse available via a .inv property, as well as via the unary ~
operator (by analogy to bitwise inverse)). I also got rid of getinv,
popinv, et al. to keep the API leaner as you recommend. I've kept the
slice syntax though as well as namedbidect, so for now I guess I'm
allowing for many ways to skin this cat.

> Just a couple of comments:
>
> Instead of:
>         self._flip = dict.__new__(self.__class__)
> I'd write:
>         self._flip = self.__class__()
> unless I'm missing something (but see the next point).

How would this not cause infinite recursion?

> Also, although Python's GC is able to handle them, I prefer to avoid  
> circular references like those between x and x._flip.  Making self._flip a  
> weak reference (and dereferencing it in the property) should be enough.

If both self._flip and self._flip._flip are weak references, no strong
references to the inverse mapping survive leaving the constructor
scope. Unless I'm missing something, only one of these can be a weak
reference, and then you'd have to do something like this in the
property to prevent "TypeError: FlipDict is not callable":

    @property
    def flip(self):
        try:
            # we're an inverse, self._flip is a weak reference
            return self._flip()
        except TypeError:
            # we're a forward mapping, self._flip is a strong
reference
            return self._flip



More information about the Python-list mailing list