Object Integer mapping

N

NighterNet

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.
 
R

Richard Thomas

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.

Richard.
 
R

Robert Kern

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
 
N

NighterNet

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,045
Messages
2,570,389
Members
47,052
Latest member
ketan

Latest Threads

Top