为什么我不能添加<some list =“”>。附加到python集?</some>

时间:2012-11-28 01:43:53

标签: python set

为什么我可以将正常的callables和方法添加到集合中,但不能<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__()也会出现此错误

3 个答案:

答案 0 :(得分:7)

您无法将list添加到集合中,因为列表是可变的。只能将不可变对象添加到集合中。

l.append是一种实例方法。您可以将其视为元组(l, list.append) - 也就是说,它是与特定列表l相关联的list.append()方法。 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'

答案 1 :(得分:3)

您不是要添加list.append。您正在尝试添加l.append这是一个实例方法,而不是类方法。 list个实例不可清除,显然它们的方法也不可清除。

这样想。你有2个清单:

lfoo = []
lbar = []

现在您要将各自的附加内容添加到您的设置中:

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

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

答案 2 :(得分:2)

在Python中,list个对象不可清除。我怀疑当你对一个实例方法进行哈希时,它会包含它所绑定的实例的哈希值。因此,您获得了TypeError