Python 使列表可变并可散列
可散列的对象需要一个Python 使列表可变并可散列,python,python-2.7,mutable,hashable,Python,Python 2.7,Mutable,Hashable,可散列的对象需要一个\uuuuuuuuuuuuuuuuu方法,并且它的散列值在其生存期内永远不会更改 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,
\uuuuuuuuuuuuuuuuu
方法,并且它的散列值在其生存期内永远不会更改
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'
L类(列表):
定义散列(自我):
返回id(自身)
a=范围(10)
l=l(范围(10))
打印
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
打印l
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
散列(l)
>> 41889288
hash(a)#毫不奇怪,它会返回一个错误,因为列表是不可哈希的
>>回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:不可损坏的类型:“列表”
#让我们在l中附加一个值
l、 追加(1000)
打印l
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1000]
isinstance(l,list)#再次检查l是否为list实例
>>真的
D={}
D[l]=“这是一个以列表为键的dict”
打印D
{[0,1,2,3,4,5,6,7,8,9,1000]:'这是一个以列表为键的dict'}
#让我们在l中附加另一个值
l、 附加(-10)
打印D
>>{[0,1,2,3,4,5,6,7,8,9,1000,-10]:'这是一个以列表为键的dict'}
#现在,让我们将一个普通列表添加到dict中
D[a]=“添加列表作为密钥”
>>回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:不可损坏的类型:“列表”
因此,这是一个可以散列的列表实现,几乎没有任何问题,我不明白为什么列表在正常的Python发行版中不能散列,即使它仍然是可变的
注意:这个问题不是关于为什么列表不能用作字典键
有什么解释吗?您有一个
\uuuu散列\uuu
方法。它返回一些东西。它返回有用的东西吗?让我看看
>>> a = L([1, 2])
>>> b = L([1, 2])
>>> a == b
True
>>> s = set([a, b])
>>> s
set([[1, 2], [1, 2]])
不!它打破了任何使用
散列
的代码所做的假设,特别是相同的对象具有相同的散列。现在我们有一个集合,其中有两个相等的对象。您可以通过使==
和来解决这个问题=代码>按标识进行比较,但这样也会丢失总订单,您必须删除
,=
。要使列表具有有意义的散列性,您必须拿出很多有用的东西。您可以使用JSON转储来比较内容质量,但有一些限制。一个限制是,这只适用于任何JSON可序列化数据
导入json
类HashableList(列表):
定义散列(自我):
返回散列(json.dumps(self,sort_keys=True))
这在大多数情况下都很有效。在任何情况下,您都需要确保它适用于您正在使用它的数据。对于可散列和可变的内容,这意味着什么?如果列表发生变化而散列没有发生变化,您如何有意义地将其用作dict键?dicts和hash表的整个概念在此分解。散列是用来区分一个键和另一个键的。如果键发生了变化,而散列没有发生变化,那么会发生什么呢?换句话说,在您的概念下,假设我创建一个dictd
,并分配d[[1,2,3]]=“alpha”
。(也就是说,键[1,2,3]
指的是'alpha'
),然后我附加到列表中。是否d[[1,2,3,4]
仍然是alpha??如果我创建一个新列表[1,2,3,4]
,该列表可能有不同的哈希值,然后将其添加到字典中,会怎么样?那么呢?从技术上讲,你是对的,但是如果你把它看作一个实例,关键是不会改变的。它的值正在改变,但不是它自己通过谷歌搜索“python列表作为字典键”找到的实例,这让我找到了一个很好的解释,解释了为什么像list
这样的可变数据类型对于字典键来说不是一个好的选择。它可以散列有什么意义?列表之所以不易损坏,并不是因为它很难,而是因为它没有意义。范围(10)=范围(10)也返回True,但范围(10)是范围(10)返回False,就像L(范围(10))是L(范围(10))返回False一样,我看不出这里有什么问题…@Cobry:是的,但你不能将它们放在一个集合中,因此,您不能将它们都放在同一个集合中,并破坏集合API。@user2357112:在Python 3中,您可以。;-)@科布里:另外,它并没有假定相同的对象具有相同的ID。假设对于任何对象a
和b
,a==b
意味着hash(a)==hash(b)
。这个属性是散列的整个点,也是它们有用的全部原因;您的\uuuuu散列\uuuuu
没有此属性。