关于python:使列表可变且可清除

Make a list mutable and hashable

一个可散列的对象需要一个__hash__方法,并且它有一个散列值,在其生存期内永远不会改变。

python列表不可散列,原因是我完全忽略了,我想知道下面的实现是否正常,或者它是否有一些我不知道的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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发行版中不能哈希,即使它仍然是可变的。

注意:这个问题不在于为什么列表不能用作字典键。有什么解释吗?


你有一个__hash__方法。它会返回一些东西。它是否返回有用的信息?让我们看看。

1
2
3
4
5
6
7
>>> a = L([1, 2])
>>> b = L([1, 2])
>>> a == b
True
>>> s = set([a, b])
>>> s
set([[1, 2], [1, 2]])

不!它打破了任何使用hash的代码所做的假设,特别是相同对象具有相同的哈希值。现在我们有一个集合,其中有两个相等的对象。你可以通过让==!=按身份进行比较来解决这个问题,尽管这样你也会失去全部顺序,你必须删除<><=>=。这是很多有用的东西,你必须拿出,使列表有意义的哈希。