Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使列表可变并可散列_Python_Python 2.7_Mutable_Hashable - Fatal编程技术网

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表的整个概念在此分解。散列是用来区分一个键和另一个键的。如果键发生了变化,而散列没有发生变化,那么会发生什么呢?换句话说,在您的概念下,假设我创建一个dict
d
,并分配
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
没有此属性。