Pre-PEP: __hashable__

Chad Netzer cnetzer at mail.arc.nasa.gov
Thu Dec 12 18:21:26 EST 2002


On Wednesday 11 December 2002 16:37, Delaney, Timothy wrote:

> That's the whole idea of this pre-PEP - to determine if it's
> worthwhile making a PEP (even if the aim is to get it rejected)
> and to see what ideas, comments people come up with so they can
> be stated in the PEP.

Well, on that notes, and with Lulu's comments in mind, I built a 
function to help with easily using dictionaries and lists (and 
other unhashable types) as keys.  It is quick and dirty, perhaps, 
but it seems to work fine.  In fact, I think it may even be 
Cookbook material.  I'd be happy to hear feedback on it.

I do think it seems to provide the same functionality that your 
proposal would be designed to provide, with no change in the 
language itself.  It costs a little bit in extra syntax, and does 
lead to __hash__() being called twice (once to determine 
hashability, then once when the dictionary actually adds the 
object).

But I think it does give a base from which to start talking about 
whether the benefits of your scheme are worth the changes.  Your 
proposal would be potentially faster, and require less typing to 
use dictionaries or lists as keys:

ie.  dct[ [1,2,3] ] = "foo"

whereas mine works as:  dct[ key( [1,2,3] ) ] = "foo"

To me, personally, it doesn't seem worth it to complicate the 
language semantics...

My thanks to Lulu (<mertz at gnosis.cx>) and Tim Delaney for the
basic ideas below; apologies for the code itself, come from me:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import pickle
import pprint

def key( obj ):
    """Return a hashable object even from mutable input objects."""

    try:
        hash( obj )
        return obj
    except TypeError:
        try:
            # Could make this a binary dump for speed
            return pickle.dumps( obj )
        except PicklingError:
            try:
                # Try to key on__repr__ and __dict__ contents
                return pprint.pformat( (obj, obj.__dict__) )
            except AttributeError:
                # Otherwise just on __repr__
                return pprint.pformat( obj )

if __name__ == '__main__':
    a = { "bacon" : 7, "baked_beans" : 8 }
    b = [1,2,3, { "spam" : 5, "eggs" : 6 } ]

    c = {}
    c[ key(a) ] = "Can keying on dictionaries work?"
    c[ key(b) ] = "How about keying on lists?"

    print ("The printout below indicates working keys "
           "from unhashable objects.")
    print
    print pprint.pformat( c )

-- 
Bay Area Python Interest Group - http://www.baypiggies.net/

Chad Netzer
cnetzer at mail.arc.nasa.gov




More information about the Python-list mailing list