Since 1 == 1.0
, it would horribly break the semantics of hashing (and therefore dicts and sets) if it were the case that hash(1) != hash(1.0)
. More generally, it must ALWAYS be the case that x == y
implies hash(x) == hash(y)
, for ALL x
and y
(there is of course no condition requiring the reverse implication to hold).
So your dict d
has just three entries, as the second one you've written in the dict display overrides the first one. If you need to force equality to hold only between identical types (as opposed to numbers more generally), you need a wrapper such as:
class W(object):
def __init__(self, x):
self.x = x
self.t = type(x)
def __eq__(self, other):
t = type(other)
if t != type(self):
return False
return self.x == other.x and self.t == other.t
def __hash__(self):
return hash(self.x) ^ hash(self.t)
def __getattr__(self, name):
return getattr(self.x, name)
Depending on your exact needs you may also want to override other methods (other comparison methods such as __cmp__
or __le__
, arithmetic ones, __repr__
, etc etc). At any rate, this will allow you to build a dict similar to what you require, just use as keys W(1)
instead of bare 1
and W(1.0)
instead of bare 1.0
(you may not need to wrap non-numbers, although there's no harm if you choose to do so, and it may ease retrieval from your dict if all keys are equally wrapped).