都不是。它是根据这些元素的散列计算的,而不是内容(值)。
是否某些东西是可以清除的,以及它是如何散列的,取决于它的.__ hash __()方法的实现。 Python本身并不知道对象的可变性。
在你的第一个例子中,元组恰好在其元素的基础上散列自身,而列表根本没有散列 – .__散列__()方法没有为它实现(并且有充分的理由)。这就是为什么在其中包含列表对象的元组不可清除的原因。
User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).
这就是为什么你不必为你的类定义.__ hash __() – 在这种情况下python为你做了。默认实现不会将实例字段带入帐户。这就是为什么你可以改变对象内部的值而不改变它的哈希值。
在这方面你是对的 – 自定义类的哈希函数的(CPython)默认实现依赖于对象的id(),而不依赖于它内部的值。它是一个实现细节,但它在Python版本之间有所不同。在更新的Python版本中,hash()和id()之间的关系涉及一些随机化。
但是它实际上如何散列呢?
虽然细节非常复杂并且可能涉及一些高级数学,但是元组对象的散列函数的实现是用C语言编写的,可以看到here(参见静态Py_hash_t tuplehash(PyTupleObject * v))。
计算涉及使用每个元组元素的哈希对一个常量进行异或运算。负责元素散列的行是这样的:
y = PyObject_Hash(*p++);
所以,回答你原来的问题:它有一堆XOR hokus-pocus与它的每个元素的哈希。是否使用这些元素的内容取决于它们的特定散列函数。