Object Integer mapping

NighterNet darkneter at gmail.com
Wed Jan 20 23:01:14 CET 2010


On Jan 20, 9:43 am, Robert Kern <robert.k... at gmail.com> wrote:
> On 2010-01-20 11:18 AM, Richard Thomas wrote:
>
>
>
> > On Jan 20, 4:43 pm, NighterNet<darkne... at gmail.com>  wrote:
> >> Need help on python version 3.1.x. I can't seem to know what going on
> >> a bit. The code that I check that the hash is different every time. Is
> >> there a way to make the hash the same? I using as to check the class
> >> is the same variables but if it different variable in the class that
> >> it add to the array and return the index.
>
> >> # Generic Object->Integer mapping
> >> # the object must be usable as a dictionary key
> >> class ObjMap:
> >>          def __init__(self):
> >>                  self.dict = {}
> >>                  self.next = 0
> >>          def get(self, obj):
> >>                  if obj in self.dict:
> >>                          return self.dict[obj]
> >>                  else:
> >>                          id = self.next
> >>                          self.next = self.next + 1
> >>                          self.dict[obj] = id
> >>                          return id
>
> >>          def items(self):
> >>                  getval = operator.itemgetter(0)
> >>                  getkey = operator.itemgetter(1)
> >>                  return map(getval, sorted(self.dict.items(), key=getkey))
>
> >> class Point:
> >>          def __init__(self):
> >>                  self.x = 0
> >>                  self.y = 0
> >>                  self.z = 0
>
> >> points = ObjMap()
>
> >> Testme = Point()
> >> Testme.x = 0
> >> print(points.get(Testme))
> >> Testme2 = Point()
> >> Testme2.y = 1
> >> print(points.get(Testme2))
> >> Testme3 = Point()
> >> Testme3.y = 1
> >> print(points.get(Testme3))
> >> Ttestme4 = Point()
> >> Ttestme4.y = 1
> >> print( points.get(Ttestme4))
>
> >> It keep adding new array from this but doesn't match hash. Need help
> >> on how to fix this class code.
>
> > You need to define how the Point class hashes. You can do this by
> > writing a __hash__ method like so:
>
> > class Point(object):
> >      ...
> >      def __hash__(self):
> >          return hash(self.x) ^ hash(self.y) ^ hash(self.z)
>
> > However you will also need to define how the Point class relates as
> > equal using the __eq__ or __cmp__ methods.
>
> > class Point(object):
> >      ...
> >      def __eq__(self, other):
> >          return self.x == other.x and self.y == other.y and self.z ==
> > other.z
>
> > This addition makes sure that if two points a equivalent then they
> > count as the same key in the dictionary.
>
> I recommend a simpler approach that duplicates less code and makes it easier to
> maintain the __hash__/__eq__ invariants:
>
> class Point(object):
>      ...
>      def _key(self):
>          # The type(self).__name__ bit is optional, but usually handy.
>          return (type(self).__name__, self.x, self.y, self.z)
>
>      def __hash__(self):
>          return hash(self._key())
>
>      def __eq__(self, other):
>          if not hasattr(other, '_key'):
>              return False
>          return self._key() == other._key()
>
> It is also worth noting that once one allows hashing by value, one should treat
> the objects as immutable, so one should not change the attributes as the OP does
> in his example.
>
> --
> Robert Kern
>
> "I have come to believe that the whole world is an enigma, a harmless enigma
>   that is made terrible by our own mad attempt to interpret it as though it had
>   an underlying truth."
>    -- Umberto Eco

Thanks you, it help fix my hash check against my classes.



More information about the Python-list mailing list