如何在Python3中结合散列码?
问题描述:
我更熟悉从子类中的超类构建复杂/组合哈希码的“Java方式”。 Python 3中有更好的/不同的/首选的方式吗? (我无法找到通过谷歌这件事具体到Python3什么。)如何在Python3中结合散列码?
class Superclass:
def __init__(self, data):
self.__data = data
def __hash__(self):
return hash(self.__data)
class Subclass(Superclass):
def __init__(self, data, more_data):
super().__init__(data)
self.__more_data = more_data
def __hash__(self):
# Just a guess...
return hash(super()) + 31 * hash(self.__more_data)
简化这个问题,请假设self.__data
和self.__more_data
简单,哈希的数据,如str
或int
。
答
The python documentation建议您使用XOR到散列结合:
仅有一个要求,就是其比较相等的对象具有相同的哈希值;建议以某种方式混合在一起(例如,使用排他或散列值)用于对象的组成部分,这些组成部分也是对象比较的一部分。
我还建议,因为该上除了XOR和乘法:
注意
hash()
截断从对象的自定义__hash__()
方法返回到Py_ssize_t
大小的值。这通常在64位版本上是8个字节,在32位版本上是4个字节。如果对象的__hash__()
必须在不同位大小的版本上互操作,请务必检查所有支持的版本的宽度。一个简单的方法来做到这一点是python -c "import sys; print(sys.hash_info.width)
“
本文档的Python 2.7和python 3.4一样的,顺便说一句。
答
我加入了一个答案,以补充托姆的。
- Python整数永远不会溢出;它们扩展为“无限”;它们不像大多数其他语言那样被限制为32位或64位,因此经典模式
x + 31 * hash(value)
将产生大量整数 - Python哈希代码应该是极限编成8个字节(64位)。因此,使用按位异或运算符
^
来组合散列码更安全。
示例代码应阅读:
class Superclass:
def __init__(self, data):
self.__data = data
def __hash__(self):
return hash(self.__data)
class Subclass(Superclass):
def __init__(self, data, more_data):
super().__init__(data)
self.__more_data = more_data
def __hash__(self):
return super().__hash__()^hash(self.__more_data)
伟大的答案。感谢您的参考。回复:“截断” - 这是由于Python的不受限制的整数值? *整数具有无限的精度*(大多数人对Python的学习感到惊讶!) – kevinarpe 2015-04-04 09:17:04
我意识到整数具有无限精度。但是,'hash()'不具有无限精度。它的实现是返回一个最可能为8个字节的“Py_ssize_t”,所以它会返回'__hash__' mod 2^64-1的结果。 – 2015-04-04 09:22:06
这是一个合理的实现:'return super().__ hash __()^ hash(self .__ more_data)'? – kevinarpe 2015-04-04 10:30:30