2015-04-03 74 views
3

我更熟悉從子類中的超類構建複雜/組合哈希碼的「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.__dataself.__more_data簡單,哈希的數據,如strint

回答

3

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一樣的,順便說一句。

+0

偉大的答案。感謝您的參考。回覆:「截斷」 - 這是由於Python的不受限制的整數值? *整數具有無限的精度*(大多數人對Python的學習感到驚訝!) – kevinarpe 2015-04-04 09:17:04

+1

我意識到整數具有無限精度。但是,'hash()'不具有無限精度。它的實現是返回一個最可能爲8個字節的「Py_ssize_t」,所以它會返回'__hash__' mod 2^64-1的結果。 – 2015-04-04 09:22:06

+0

這是一個合理的實現:'return super().__ hash __()^ hash(self .__ more_data)'? – kevinarpe 2015-04-04 10:30:30

0

我加入了一個答案,以補充託姆的。

  1. Python整數永遠不會溢出;它們擴展爲「無限」;它們不像大多數其他語言那樣被限制爲32位或64位,因此經典模式x + 31 * hash(value)將產生大量整數
  2. 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)