patternpythonMinor
Class for simple python object to be hashed and referenced
Viewed 0 times
simplereferencedhashedpythonforandobjectclass
Problem
I need objects in python that I can compare, reference to and hash.
In principal a tuple or list would be good enough just that
a list I cannot hash and the tuple I cannot change,
except replacing it which means losing references to it.
So I created a class for it, but still have the feeling there should be a simpler/better solution to it.
Now I can do what I need: creating some objects
and some references
and compare, manipulate ...
I wished I could just forget about the class and do
etc ...
Is writing this class the best way to approach this problem? Or did I miss something?
edit:
After the comment by WinstonEwert I confirmed that the objects cause breakage as keys in dictionary
and decided to replace dictionaries that use these objects as keys by
```
class MyDict:
def __init__(self, d={}):
self._data = d.items()
def __getitem__(self, key):
for k, v in self._data:
if k == key: return v
raise KeyError
def __setitem__(self, key, value):
for i, (k, v) in enumerate(self._data):
if k == key:
self._data[i] = key, value
return
self._data.append((key,value))
def __contains__(self, key):
In principal a tuple or list would be good enough just that
a list I cannot hash and the tuple I cannot change,
except replacing it which means losing references to it.
So I created a class for it, but still have the feeling there should be a simpler/better solution to it.
class MyClass:
def __init__(self, k, l=0, m=0):
self.k = k
self.l = l
self.m = m
def __hash__(self):
n_attr = len(self.__dict__)
return sum(hash(attr)/n_attr for attr in self.__dict__.values())
def __eq__(self, other):
return all(sa==oa for sa, oa in zip(self.__dict__.values(),
other.__dict__.values()))Now I can do what I need: creating some objects
x = MyClass(1,2,3)
y = MyClass(7)
z = MyClass(7,1,0)and some references
a = x; b = y; c = y; d = zand compare, manipulate ...
b == c # True
b == d # False
b.l = 1
b == c # still True
b == d # now True
s = {a, d, (a,b)}
b in s # True
c in s # True
(a,c) in s # TrueI wished I could just forget about the class and do
x = 1,2,3
y = 7,
z = 7,1etc ...
Is writing this class the best way to approach this problem? Or did I miss something?
edit:
After the comment by WinstonEwert I confirmed that the objects cause breakage as keys in dictionary
s = {a: 'a', b: 'b'}
s[c] # 'b'
c.l = 99
s[c] # key error
s # key errorand decided to replace dictionaries that use these objects as keys by
```
class MyDict:
def __init__(self, d={}):
self._data = d.items()
def __getitem__(self, key):
for k, v in self._data:
if k == key: return v
raise KeyError
def __setitem__(self, key, value):
for i, (k, v) in enumerate(self._data):
if k == key:
self._data[i] = key, value
return
self._data.append((key,value))
def __contains__(self, key):
Solution
The python dictionary assumes that the keys are immutable. It assumes they will not change. That's why mutable classes in python (such as lists) don't hash. Its to prevent you from putting them in dicts which just won't work.
As a result the entire premise of your class is wrong. You shouldn't do that. To follow what python expects, an object should return the same hash and be equal to the same objects throughout its lifetime. If it can't it shouldn't support hashing.
We might be able to suggest a better way to do this, but you'll need to show more of how you want to use this class.
As a result the entire premise of your class is wrong. You shouldn't do that. To follow what python expects, an object should return the same hash and be equal to the same objects throughout its lifetime. If it can't it shouldn't support hashing.
We might be able to suggest a better way to do this, but you'll need to show more of how you want to use this class.
Context
StackExchange Code Review Q#26008, answer score: 4
Revisions (0)
No revisions yet.