【问题标题】:How does the hash function for a tuple work元组的哈希函数如何工作
【发布时间】:2019-12-15 09:54:23
【问题描述】:

根据我对 Python 的理解,由于元组是不可变的,它们应该是可散列的,hash() 函数应该对它们起作用。然而,情况似乎并非如此,因为当它们包含列表或字典等项目时,哈希函数会报错,如下所示。

这行得通:

>>> t = (1, 2, 'name', 'Subhayan', 'age', 32, 'sex', 'male')
>>> hash(t)
3584505648807432737

这不起作用:

>>> t = ({'First': 1, 'second': 2}, 'age', 32, 'sex', 'male', 'name', 'Subhayan')
>>> hash(t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

所以我的问题是哈希函数在内部是如何运作的?它是否遍历元组并尝试散列各个组件?

谁能给我一些关于它是如何工作的参考。

【问题讨论】:

  • 如果一个元组包含一个可变对象,它不得是可散列的。它可以更改其哈希值,使大多数依赖哈希函数的实现变得无用。

标签: python hash


【解决方案1】:

是的,不可变容器的哈希值采用包含对象的哈希值。

对于元组,请参阅 Objects/tupleobject.c 源代码,特别是 tuplehash function

static Py_hash_t
tuplehash(PyTupleObject *v)
{
    Py_uhash_t x;  /* Unsigned for defined overflow behavior. */
    Py_hash_t y;
    Py_ssize_t len = Py_SIZE(v);
    PyObject **p;
    Py_uhash_t mult = _PyHASH_MULTIPLIER;
    x = 0x345678UL;
    p = v->ob_item;
    while (--len >= 0) {
        y = PyObject_Hash(*p++);
        if (y == -1)
            return -1;
        x = (x ^ y) * mult;
        /* the cast might truncate len; that doesn't change hash stability */
        mult += (Py_hash_t)(82520UL + len + len);
    }
    x += 97531UL;
    if (x == (Py_uhash_t)-1)
        x = -2;
    return x;
}

在 Python 中,忽略 C 的 int 类型溢出,相当于:

_PyHASH_MULTIPLIER = 1000003  # from pyhash.h

def tuplehash(v):
    x = 0x345678
    mult = _PyHASH_MULTIPLIER
    l = len(v)
    for i, ob in enumerate(v, 1):
        y = hash(ob)
        x = ((x ^ y) * mult)
        mult += (82520 + 2 * (l - i))
    x += 97531
    return x

“幻数”可确保元组散列为内容散列中的微小变化产生广泛的值。

毕竟这是最合乎逻辑的实现;哈希应该反映包含的值,并且当您针对另一个元组测试相等性时,包含的值也会针对另一个元组中的对象进行测试;哈希和相等功能密切相关。

元组可以引用任何类型的对象;元组本身不能改变,但这并不意味着你不能改变它引用的对象。这一点,元组的散列性取决于元组引用的对象的散列性。

【讨论】:

  • Python的实现循环中不应该有“l = l - 1”吗?
  • @jianchang:len 变量减少了:--len,想起来,我在我的 Python 版本中忘记了。我现在已经纠正了这个错误。
猜你喜欢
  • 2019-10-06
  • 1970-01-01
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2017-10-02
  • 2010-11-30
相关资源
最近更新 更多