7

为什么我可以将普通的可调用对象和方法添加到集合中,但不能<some list>.append(例如)?

例如:

>>> l = []
>>> s = set()
>>> s.add(l.append)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> type(l.append)
<type 'builtin_function_or_method'>
>>> type(map)
<type 'builtin_function_or_method'>
>>> s.add(map)
>>> def func(): print 'func'
... 
>>> s.add(func)
>>> print s
set([<built-in function map>, <function func at 0x10a659758>])

编辑:我注意到这l.append.__hash__()也给出了这个错误

4

3 回答 3

8

您不能将lists 添加到集合中,因为列表是可变的。只有不可变的对象可以添加到集合中。

l.append是一个实例方法。你可以把它想象成元组(l, list.append)——也就是说,它是绑定到特定列表的 list.append() 方法l。list.append() 方法是不可变的,但l不是。因此,虽然您可以添加list.append到集合中,但您无法添加l.append.

这有效:

>>> s.add(list.append)

这不起作用:

>>> s.add((l, list.append))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
于 2012-11-28T01:48:31.010 回答
3

您没有尝试添加list.append. 您正在尝试添加l.append哪个是实例方法,而不是类方法。 list实例不可散列,显然它们的方法也不可散列。

这样想吧。您有 2 个列表:

lfoo = []
lbar = []

现在您想将它们各自的附加添加到您的集合中:

s = set()
s.add(lfoo.append)
s.add(lbar.append)

现在,当您对集合进行哈希查找时,不能只依赖实例方法的函数部分。确实,lfoolbar最终使用相同的功能(list.append)。所以这不是一个唯一的哈希。使其独一无二的方法是将其附加到实例上。但是,该实例不支持散列,因此该集合无法分辨lfoo.append和之间的区别lbar.append

于 2012-11-28T01:45:48.953 回答
2

在 Python 中,list对象是不可散列的。我怀疑当你散列一个实例方法时,它包含了它绑定到的实例的散列。这样,您将获得TypeError.

于 2012-11-28T01:46:55.273 回答