我有一个 dict 实例,其中 int、float、string 作为键,但是问题是当 a 为 int 和 b 为 float 和 float(a) == b,那么它们的哈希值是相同的,这就是我不想得到的,因为在这种情况下我需要唯一的哈希值才能获得相应的值。
例子:
d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0}
d[1] == '1.0'
d[1.0] == '1.0'
d['1'] == 1
d['1.0'] == 1.0
我需要的是:
d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0}
d[1] == '1'
d[1.0] == '1.0'
d['1'] == 1
d['1.0'] == 1.0
请您参考如下方法:
自 1 == 1.0 以来,如果 hash(1) != hash(1.0) 会严重破坏散列的语义(因此也破坏了字典和集合) 。更一般地说,对于所有 x,x == y 必须始终是 hash(x) == hash(y)和 y(当然没有条件要求反向蕴涵成立)。
因此您的字典 d 只有三个条目,因为您在字典显示中写入的第二个条目会覆盖第一个条目。如果你需要强制只在相同类型之间保持相等(而不是更普遍的数字),你需要一个包装器,例如:
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)
根据您的具体需要,您可能还想覆盖其他方法(其他比较方法,例如 __cmp__ 或 __le__,算术方法,__repr__ 等)。无论如何,这将允许您构建一个类似于您需要的字典,只需使用 W(1) 而不是裸露的 1 和 W( 1.0) 而不是裸露的 1.0 (您可能不需要包装非数字,尽管如果您选择这样做也没有坏处,并且如果所有键都可以简化从字典中的检索同样包裹)。
