Return the hash value of the object (if it has one). Hash values are
integers. They are used to quickly compare dictionary keys during a
dictionary lookup. Numeric values that compare equal have the same
hash value (even if they are of different types, as is the case for 1
and 1.0).
Called by built-in function hash() and for operations on members of
hashed collections including set, frozenset, and dict. __hash__()
should return an integer. The only required property is that objects
which compare equal have the same hash value;
首先:hash函数的文档中明确记录了该行为:
其次,在^{} 的文档中指出了散列的限制
这不是python独有的。Java也有同样的警告:如果您实现了
hashCode
,那么为了让事情正常运行,您必须以这样一种方式实现它:x.equals(y)
意味着x.hashCode() == y.hashCode()
因此,python决定
1.0 == 1
保持不变,因此它被迫为hash
提供一个实现,以便hash(1.0) == hash(1)
。副作用是1.0
和1
的行为与dict
键的行为完全相同,因此这种行为是正确的换句话说,行为本身不必以任何方式使用或有用这是必要的。如果没有这种行为,您可能会意外地覆盖不同的密钥
如果我们有
1.0 == 1
但是hash(1.0) != hash(1)
,我们仍然可以有一个碰撞。如果1.0
和1
发生冲突,dict
将使用相等来确定它们是否是同一个键,kaboom即使您希望它们不同,也会覆盖该值避免这种情况的唯一方法是使用
1.0 != 1
,这样dict
即使在发生冲突的情况下也能够区分它们。但是,人们认为拥有1.0 == 1
比避免你看到的行为更重要,因为你实际上从来没有使用float
和int
作为字典键由于python试图通过在需要时自动转换数字(例如
1/2 -> 0.5
)来隐藏数字之间的区别,因此即使在这种情况下也可以反映这种行为。它与python的其他部分更加一致这种行为会出现在任何实现中,其中键的匹配至少部分地(如在哈希映射中)基于比较
例如,如果一个
dict
是使用红黑树或其他类型的平衡BST实现的,当查询键1.0
时,与其他键的比较将返回与1
相同的结果,因此它们仍然以相同的方式工作散列映射需要更加小心,因为用于查找密钥项的是散列值,只有在之后才进行比较。因此,违反上述规则意味着您将引入一个很难发现的错误,因为有时
dict
可能会像您预期的那样工作,而在其他时候,当大小发生变化时,它将开始表现不正确注意,将有一种方法来解决这个问题:为字典中插入的每种类型都有一个单独的hash-map/BST。通过这种方式,不同类型的对象之间不会发生任何冲突,并且当参数具有不同类型时,
==
的比较方式也无关紧要然而,这将使实现复杂化,这可能是低效的,因为哈希映射必须保留相当多的空闲位置才能有O(1)个访问时间。如果它们变得太满,性能就会下降。拥有多个哈希映射意味着浪费更多空间,而且在开始实际查找密钥之前,您需要首先选择要查看的哈希映射
如果使用BST,则必须首先查找类型,然后执行第二次查找。因此,如果您要使用许多类型,那么最终的工作量将是原来的两倍(并且查找将需要O(logn)而不是O(1))
您应该考虑到^ {CD1>}的目的是根据逻辑数值存储数据,而不是如何表示它。p>
int
和float
之间的区别实际上只是一个实现细节,而不是概念性的。理想情况下,唯一的数字类型应该是具有无限精度甚至亚单位的任意精度数字。。。然而,如果不遇到麻烦,这是很难实现的。。。但这可能是Python未来唯一的数字类型因此,由于技术原因,Python使用不同的类型时,会试图隐藏这些实现细节和
int
->float
转换是自动的如果在Python程序中,当
x
是一个值为1的float
时if x == 1: ...
不会被接受,那就更令人惊讶了请注意,在Python3中,
1/2
的值是0.5
(两个整数的除法),类型long
和非unicode字符串也被删除,同时尝试隐藏实现细节在python中:
这是因为隐式铸造
然而:
我可以理解为什么在
float
和int
之间进行自动强制转换很方便,将int
强制转换为float
相对安全,但是还有其他语言(例如go)不进行隐式强制转换这实际上是一个语言设计的决定,而不仅仅是不同功能的品味问题
相关问题 更多 >
编程相关推荐