散列函数问题:hash(1)== hash(1.0)

mta*_*c85 1 python hash dictionary

我有一个实例dictintS,floatS,stringS作为密钥,但问题是当有a作为intb作为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
Run Code Online (Sandbox Code Playgroud)

我需要的是:

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
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 7

因为1 == 1.0,如果是这样的话,它会极大地破坏散列的语义(因此也会破坏词汇和集合)hash(1) != hash(1.0).更一般地,它必须始终是的情况下x == y意味着hash(x) == hash(y),对于所有xy(当然还有不要求反向含义保持状态).

所以你的dict d只有三个条目,因为你在dict显示中写的第二个条目会覆盖第一个条目.如果你需要强制相等只在相同的类型之间保持(而不是更普遍的数字),你需要一个包装器,如:

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)
Run Code Online (Sandbox Code Playgroud)

根据您的确切需要,您可能还想覆盖其他方法(其他比较方法,如__cmp____le__,算术__repr__等).无论如何,这将允许你构建一个类似于你需要的dict,只需用作键W(1)而不是裸1,W(1.0)而不是裸1.0(你可能不需要包装非数字,尽管如果你选择这样做也没有坏处如果所有键都被平均包裹,它可以简化从你的字典中的检索.


Mar*_*ett 6

使用float作为字典键是"不明智的",不可能保证两个浮点数将评估为相同的值.

最好的方法是将键乘以预定的小数位数,并使用该整数作为键.

编辑:对不起,似乎你不想要一个带有实数键的字典,你只想根据输入的类型格式化输出?