Possibly dumb question about dicts and __hash__()

johnzenger at gmail.com johnzenger at gmail.com
Wed May 3 16:39:08 EDT 2006


Actually, come to think of it, __str__ works just as well.

>>> class NamedThing(object):
     def __init__(self, name):
         self.name = name
     def __str__(self):
         return self.name
>>> d = {}
>>> d[a] = 1
>>> d[b] = 50
>>> d
{<__main__.NamedThing object at 0x00C528D0>: 1, <__main__.NamedThing
object at 0x00C529B0>: 50}
>>> d[a]
1
>>> d[b]
50

This is what you should use, instead of my first answer.  From the docs
for __repr__: "If at all possible, this should look like a valid Python
expression that could be used to recreate an object with the same value
(given an appropriate environment). If this is not possible, a string
of the form "<...some useful description...>" should be returned. ...
This is typically used for debugging, so it is important that the
representation is information-rich and unambiguous."



johnzenger at gmail.com wrote:
> Use __repr__.  Behold:
>
> >>> class NamedThing(object):
>      def __init__(self, name):
>          self.name = name
>      def __repr__(self):
>          return self.name
>
> >>> a = NamedThing("Delaware")
> >>> b = NamedThing("Hawaii")
> >>> d = {}
> >>> d[a] = 1
> >>> d[b] = 50
> >>> print d
> {Delaware: 1, Hawaii: 50}
> >>> d[a]
> 1
> >>> d[b]
> 50
>
> Although this is a bit illegal, because repr is not supposed to be used
> this way.
>
> Joel Hedlund wrote:
> > Hi!
> >
> > There's one thing about dictionaries and __hash__() methods that puzzle me. I
> > have a class with several data members, one of which is 'name' (a str). I would
> > like to store several of these objects in a dict for quick access
> > ({name:object} style). Now, I was thinking that given a list of objects I might
> > do something like
> >
> > d = {}
> > for o in objects:
> >      d[o] = o
> >
> > and still be able to retrieve the data like so:
> >
> > d[name]
> >
> > if I just defined a __hash__ method like so:
> >
> > def __hash__(self):
> >      return self.name.__hash__()
> >
> > but this fails miserably. Feel free to laugh if you feel like it. I cooked up a
> > little example with sample output below if you care to take the time.
> >
> > Code:
> > ---------------------------------------------------------------
> > class NamedThing(object):
> >      def __init__(self, name):
> >          self.name = name
> >      def __hash__(self):
> >          return self.name.__hash__()
> >      def __repr__(self):
> >          return '<foo>'
> > name = 'moo'
> > o = NamedThing(name)
> > print "This output puzzles me:"
> > d = {}
> > d[o] = o
> > d[name] = o
> > print d
> > print
> > print "If I wrap all keys in hash() calls I'm fine:"
> > d = {}
> > d[hash(o)] = o
> > d[hash(name)] = o
> > print d
> > print
> > print "But how come the first method didn't work?"
> > ---------------------------------------------------------------
> >
> > Output:
> > ---------------------------------------------------------------
> > This output puzzles me:
> > {'moo': <foo>, <foo>: <foo>}
> >
> > If I wrap all keys in hash() calls I'm fine:
> > {2038943316: <foo>}
> >
> > But how come the first method didn't work?
> > ---------------------------------------------------------------
> >
> > I'd be grateful if anyone can shed a litte light on this, or point me to some
> > docs I might have missed.
> >
> > Also:
> > Am I in fact abusing the __hash__() method? If so - what's the intended use of
> > the __hash__() method?
> >
> > Is there a better way of implementing this?
> >
> > I realise I could just write
> >
> > d[o.name] = o
> >
> > but this problem seems to pop up every now and then and I'm curious if there's
> > some neat syntactic trick that I could legally apply here.
> > 
> > Thanks for your time!
> > /Joel Hedlund




More information about the Python-list mailing list