On 2010-01-20 11:18 AM, Richard Thomas wrote:
On Jan 20, 4:43 pm, NighterNet<darkne...@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

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to