2015-11-08 30 views
0

docs錯誤地宣稱什麼是用戶定義的類的默認散列?

對象,其是用戶定義的類的實例是由缺省可哈希;他們都比較不平等的(除了自己),他們的哈希值是他們id()

雖然我記得這是正確一次,散列等於其ID這樣的對象顯然不是在蟒蛇(V2的當前版本真。 7.10,v3.5.0)。

>>> class A: 
...  pass 
... 
>>> a = A() 
>>> hash(a) 
-9223372036578022804 
>>> id(a) 
4428048072 

在文檔的another part它說,散列衍生從ID。何時/爲什麼執行更改,並且現在由散列「派生自」id返回的數字如何?

回答

3

相關功能似乎是:

Py_hash_t 
_Py_HashPointer(void *p) 
{ 
    Py_hash_t x; 
    size_t y = (size_t)p; 
    /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid 
     excessive hash collisions for dicts and sets */ 
    y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)); 
    x = (Py_hash_t)y; 
    if (x == -1) 
     x = -2; 
    return x; 
} 

(即代碼來自here,然後用來爲tp_hash插槽typehere)的評論似乎給了不是理由直接使用指針(與id相同)。事實上,提交介紹了這種變化的功能是here,並指出了變化的原因是:

問題#5186:通過旋轉對象減少對象的哈希衝突沒有散列 方法指針向右4位。

這是指this問題,這更多地解釋了爲什麼進行更改。

1

由於issue #5186在2009年發生了變化;通常id()值引起太多的碰撞:

In the issue 5169 discussion, Antoine Pitrou suggested that for an object 
x without a `__hash__` method, `id()/8` might be a better hash value than 
`id()`, since dicts use the low order bits of the hash as initial key, and 
the 3 lowest bits of an `id()` will always be zero. 

current implementation取ID和轉動時,它產生更變化值:

long 
_Py_HashPointer(void *p) 
{ 
    long x; 
    size_t y = (size_t)p; 
    /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid 
     excessive hash collisions for dicts and sets */ 
    y = (y >> 4) | (y << (8 * SIZEOF_VOID_P - 4)); 
    x = (long)y; 
    if (x == -1) 
     x = -2; 
    return x; 
} 

這導致14%至34%的加速,這取決於在進行測試。

詞彙表是過時的;我看到你already opened an issue with the project

相關問題