为什么 Python 不能以数字作为字典键?

x33g5p2x  于2021-11-03 转载在 Python  
字(1.0k)|赞(0)|评价(0)|浏览(519)

平时有事没事就在 Stack Overflow 上闲逛,这里有很多关于 Python 的有趣问题。的确有些问题在我们的生活中可能永远不会遇到。然而,背后的知识却相当有趣,甚至比问题本身更有趣。

在本文中,我就分享 Python 中的一个“神秘”字典 Keys ,并尝试解释它。喜欢本文点赞支持,文末加群欢迎畅聊。

字典Keys

让我们定义一个使用整数、浮点数和字符串作为键的字典, 从含义上看,它们都是“1”。

my_dict = {
    1: 'one (integar)',
    '1': 'one (string)',
    1.0: 'one point zero (float)'
}

现在,让我们尝试使用Keys获取值。

等等,第一个不对。 看起来 my_dict[1] 的值已被 my_dict[1.0] 覆盖,让我们尝试不同的顺序来验证它。

这一次,my_dict[1] 的值覆盖了 my_dict[1.0]。 因此,后来定义的人将覆盖前一个。 这意味着密钥 1 和 1.0 是相同的。

背后的原因

我们先来看看Python官方文档:
hash(object)
返回对象的哈希值(如果有的话)。 哈希值是整数。 它们用于在字典查找期间快速比较字典键。 比较相等的数值具有相同的哈希值(即使它们属于不同类型,如 1 和 1.0 的情况)。

它基本上已经说明了原因。 我们传入的字典的键将被散列以进行比较,不幸的是,某些不同类型的散列值是相同的。 我们可以验证这一点。

事实上,这并不是 Python 独有的,在 Java 中也是如此。 如果你实现了 hashCode,为了使事情正常工作,你必须确保 x.equals(y) 隐含 x.hashCode() == y.hashCode()。

回到 Python,1.0 == 1 在 Python 中是 True。 因此,必须实现散列函数以确保 hash(1.0) == hash(1)。 字典键的神秘行为是其“副作用”。

另一个问题

基于以上事实,你还认为用表达式作为字典键可以吗? 不,这仍然是一个坏主意。 让我们看看下面的例子。

因此,可以预期以下示例将不起作用。

这一次,这两个哈希函数的值是不同的。 为什么? 他们不是同一个数字0.8吗?(10.0-9.2) 实际上不完全是 0.8。 这是所有平台上典型的二进制浮点算术问题。

Python 给出了以下文档来阐明这个问题。

https://docs.python.org/3/tutorial/floatingpoint.html

因此,请不要使用数字作为字典键。

相关文章