Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 哈希函数有问题:哈希(1)=哈希(1.0)_Python_Hash_Dictionary - Fatal编程技术网

Python 哈希函数有问题:哈希(1)=哈希(1.0)

Python 哈希函数有问题:哈希(1)=哈希(1.0),python,hash,dictionary,Python,Hash,Dictionary,我有一个用ints、floats、strings作为键的dict实例,但问题是当有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

我有一个用
int
s、
float
s、
string
s作为键的
dict
实例,但问题是当有
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.00001或类似的值吗?

这并不能解决你的问题,但可以从以下方面入手:

实现者应该小心地使相等的数字相等,并将它们散列为相同的值


将浮点值设为1.00001或类似的值可以吗?

将浮点值用作字典键是“不明智的”,无法保证两个浮点值的计算结果相同

最好的方法是将这些键相乘到预定的小数位数,并使用该整数作为键


编辑:很抱歉,您似乎不想要带有实数键的dict,您只想根据输入类型格式化输出?

使用浮点作为字典键是“不明智的”,无法保证两个浮点将计算为相同的值

最好的方法是将这些键相乘到预定的小数位数,并使用该整数作为键


编辑:很抱歉,您似乎不想要带有实数键的dict,您只需要根据输入类型格式化输出?

由于
1==1.0
,如果
hash(1)!=哈希(1.0)
。更一般地说,对于所有
x
y
,必须始终是
x==y
意味着
hash(x)==hash(y)
(当然没有条件要求反向蕴涵成立)

因此,您的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)

根据您的具体需要,您可能还希望覆盖其他方法(其他比较方法,如
\uu cmp\uuuuu
\uuuu le\uuuuuu
、算术方法、
\uu repr\uuuu
等)。无论如何,这将允许您构建与所需类似的dict,只需将其用作键
W(1)
而不是裸
1
W(1.0)
而不是裸
1.0
(您可能不需要包装非数字,但如果您选择这样做也没有坏处,而且如果所有键都被同等包装,则可以轻松地从dict检索)。

由于
1==1.0
,如果是
哈希(1)!=hash(1.0)的情况,它将可怕地破坏哈希的语义(因此也会破坏dicts和set)
。更一般地说,对于所有
x
y
,必须始终是
x==y
意味着
hash(x)==y
(当然,没有条件要求反向蕴涵成立)

因此,您的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)

根据您的具体需要,您可能还希望覆盖其他方法(其他比较方法,如
\uuu cmp\uuu
\uuu le\uuuu
、算术方法、
\uu repr\uuu
等)。无论如何,这将允许您构建一个类似于您所需的dict,只需用作键
W(1)
而不是bare
1
W(1.0)
而不是bare
1.0
(您可能不需要包装非数字,但如果您选择这样做也没有坏处,并且如果所有键都被同等包装,则可以轻松地从dict检索).

如果你真的只想知道其中的区别,也许可以做一些黑客行为,比如:

x = '1'
y = 1

hash(type(x) + x) != hash(type(y) + y)

如果你真的只想知道两者的区别,也许可以做一些粗俗的事情,比如:

x = '1'
y = 1

hash(type(x) + x) != hash(type(y) + y)

好的一点,但我也知道我可以为所有关键类型创建一个新类,并为所有其他类型创建一个单独的dict,以备需要,其中setitem、getitem和delitem方法可以确定使用哪个dict来存储键和值。好的一点,但我也知道我可以创建一个单独的dict的新类所有关键类型的dict加上所有其他类型的dict,以防我需要它们,其中setitem、getitem和delitem方法可以确定用于存储键和值的dict。包装对象可以被视为一种解决方案,它非常接近我需要的。无论如何,我想知道以下内容:h=hash('a');d={'a':1,h:2};结果是d['a']!=d[h]因为键的散列值相同,但它们的类型不同,这意味着dict方法getitem同时检查键的散列值和键的类型。如果是这样,为什么int和float的检查方式不同?@mtasic,您是在问为什么在每个上下文中
1==1.0
,或者为什么
dict
s使用
=
而不是其他方法来检查如果你问的是前者,想想:如果
5.0*x==5.0*y
,它怎么可能是
x!=y
,而不打破算术和代数最基本的期望?如果是后者,如果
x==y
但是
d[x]!=d[y],那么
dict
怎么可能是一个映射呢
?这些都是强大、珍贵、强烈期望的等式、算术和索引的不变属性,类型拜物教并不是打破它们的好理由;等式