簡體   English   中英

命名元組存在於哈希集中

[英]Named tuples existence in a hashset

In [1]: x = set()
In [2]: pos = collections.namedtuple('Position', ['x','y'])
In [4]: x.add(pos(1,1))
In [5]: x
Out[5]: {Position(x=1, y=1)}
In [6]: pos(1,1) in x
Out[6]: True
In [8]: pos(1,2) in x
Out[8]: False

我沒想到pos(1,1) in x可以工作。 因為 pos(1,1) 似乎每次都會創建一個 object 和不同的 object id。

In [9]: id(pos(1,1))
Out[9]: 140290954200696
In [10]: id(pos(1,1))
Out[10]: 140290954171016

在這種情況下,set in運算符如何處理命名元組? 它會檢查 namedtuple 的內容嗎?

namedtuple 並不特別。 該元素應該完全相等( __eq__ )並且必須具有相似的hash才能通過包含測試。

>>> hash(pos(1, 1)) == hash(pos(1, 1))
True
>>> pos(1, 1) == pos(1, 1)
True

如果您有興趣, 請參閱此處的實現set().__contains__(y)首先必須計算yhash值。

static int
set_contains_key(PySetObject *so, PyObject *key)
{
    Py_hash_t hash;

    if (!PyUnicode_CheckExact(key) ||
        (hash = _PyASCIIObject_CAST(key)->hash) == -1) {
        hash = PyObject_Hash(key);
        if (hash == -1)
            return -1;
    }
    return set_contains_entry(so, key, hash);
}

但是單獨計算hash並不能說明元素是否相等。 例如

>>> hash(-1)
-2
>>> hash(-2)
-2

這意味着如果 hash 值相等,則需要進行__eq__檢查以確認元素是否完全相等

請注意,我的回答完全基於 Cpython 實現。

可散列對象的元組是可散列的,因此它可以用作集合的成員,因此可以通過in檢查。
由於您使用數字作為元組值,這顯然是可散列的,因此散列整個元組沒有問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM