可散列的对象需要__hash__
方法,并且它的哈希值在其生命周期内永远不会改变。
由于我完全忽略的原因,Python列表不可清除,我想知道以下实现是否正常,或者是否有一些我不知道的故障。
class L(list):
def __hash__(self):
return id(self)
a = range(10)
l = L(range(10))
print a
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print l
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
hash(l)
>> 41889288
hash(a) # unsurprisingly it returns an error because a list is not hashable
>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
# lets append a value to l
l.append(1000)
print l
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000]
isinstance(l, list) # to double check whether l is a List instance
>> True
D = {}
D[l] = "this is a dict with a list as key"
print D
{[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000]: 'this is a dict with a list as key'}
# lets append another value to l
l.append(-10)
print D
>> {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000, -10]: 'this is a dict with a list as key'}
# now lets add a normal list to the dict to the dict
D[a] = "Add a list as key"
>>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
所以这是一个可以使用的清单实现,几乎没有任何问题,我不明白为什么列表在普通的Python发行版中不能被清除,即使它仍然是可变的。
注意:这个问题不是为什么列表不能用作字典键 有什么解释吗?
答案 0 :(得分:7)
您有__hash__
方法。它返回一些东西。它会返回有用的东西吗?我们来看看。
>>> a = L([1, 2])
>>> b = L([1, 2])
>>> a == b
True
>>> s = set([a, b])
>>> s
set([[1, 2], [1, 2]])
都能跟得上!它打破了使用hash
的任何代码所做出的假设,特别是相等的对象具有相等的哈希值。现在我们有一个包含两个相等对象的集合。你可以通过==
和!=
按身份进行比较来解决这个问题,但是你也会失去总订单,你必须删除<
,>
,{{1 }和<=
。这是很多有用的东西,你必须拿出来使列表有意义的可用。
答案 1 :(得分:0)
您可以(有限制)使用JSON转储来比较按内容分类的质量。一个限制是,它仅适用于任何JSON可序列化的数据。
import json
class HashableList(list):
def __hash__(self):
return hash(json.dumps(self, sort_keys=True))
这在大多数情况下都可以正常工作。无论如何,您都需要确保此方法适用于您所使用的数据。