Re: Possibly dumb question about dicts and __hash__()
Hi! > Just the hash is not enough. You need to define equality, too: Thanks a million for clearing that up. Cheers! /Joel -- http://mail.python.org/mailman/listinfo/python-list
Re: Possibly dumb question about dicts and __hash__()
Joel Hedlund wrote: > 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__() Just the hash is not enough. You need to define equality, too: >>> class Named(object): ... def __init__(self, name): ... self.name = name ... def __hash__(self): ... return hash(self.name) ... def __eq__(self, other): ... try: ... other_name = other.name ... except AttributeError: ... return self.name == other ... return self.name == other_name ... def __repr__(self): ... return "Named(name=%r)" % self.name ... >>> items = [Named(n) for n in "alpha beta gamma".split()] >>> d = dict(zip(items, items)) >>> d["alpha"] Named(name='alpha') Peter -- http://mail.python.org/mailman/listinfo/python-list
Re: Possibly dumb question about dicts and __hash__()
Beautiful! But how come my attempt didn't work? I've seen docs that explain how __hash__() methods are used to put objects in dict buckets: http://docs.python.org/ref/customization.html#l2h-195 But if it's really hash(str(o)) that's used for dict keys, what good are __hash__() methods? Or am I reading the docs wrong? /Joel -- http://mail.python.org/mailman/listinfo/python-list
Re: Possibly dumb question about dicts and __hash__()
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." [EMAIL PROTECTED] 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 '' > > 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': , : } > > > > If I wrap all keys in hash() calls I'm fine: > > {2038943316: } > > > > 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Possibly dumb question about dicts and __hash__()
Joel Hedlund a écrit : (snip) > How illegal is it? If I document it and put it in an opensource project, > will people throw tomatoes? Don't know, but they'll sure do if you insist on top-posting !-) -- http://mail.python.org/mailman/listinfo/python-list
Re: Possibly dumb question about dicts and __hash__()
Hi! Thanks for the quick response! > Although this is a bit illegal, because repr is not supposed to be used > this way. How illegal is it? If I document it and put it in an opensource project, will people throw tomatoes? /Joel [EMAIL PROTECTED] 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 '' >>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': , : } >> >>If I wrap all keys in hash() calls I'm fine: >>{2038943316: } >> >>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 > > -- http://mail.python.org/mailman/listinfo/python-list
Re: Possibly dumb question about dicts and __hash__()
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 '' > 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': , : } > > If I wrap all keys in hash() calls I'm fine: > {2038943316: } > > 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 -- http://mail.python.org/mailman/listinfo/python-list
Possibly dumb question about dicts and __hash__()
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 '' 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': , : } If I wrap all keys in hash() calls I'm fine: {2038943316: } 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 -- http://mail.python.org/mailman/listinfo/python-list