2012-11-28 42 views
5

爲什麼我可以添加普通的可調式和方法到一個集合,但不是<some list>.append(例如)?爲什麼我不能將<some list> .append添加到Python集合中?

例如:

>>> 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__()你不是想添加list.append也給出了這樣的錯誤

+0

什麼是你真的* *意欲何爲? o_O –

+0

@KarlKnechtel我正在使用twisted.trial編寫測試。我有一個事件總線系統,它記錄事件的回調(由一個字符串指定)並將回調存儲在一個集合中以防止重複。這個特定的回調只是results_list.append的一個包裝,所以我試圖直接註冊爲回調。測試觸發一個事件,並檢查results_list以查看它是否包含數據。 –

回答

7

您不能將list s添加到集合,因爲列表是可變的。只有不可變的對象才能被添加到集合中。

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' 
+0

我站好了。我猜想,這並不令人意外,......令人驚訝的是,我經歷了一生,總是認爲所有的元組都是可排除的:) – mgilson

+1

這種行爲是有道理的。起初,我認爲你可以回退對象ID,但這是行不通的,因爲當你嘗試用不同的(等價的)元組索引你的字典時,你會做什麼:'d [(500,600)] = ...'。由於ID的不同,這種常見用例會失敗。散列元組的唯一方法是對每個元素進行散列。很有意思。 – mgilson

3

。你試圖添加l.append這是一個實例方法,而不是一個類方法。 list實例不可哈希,顯然他們的方法也不可哈希。

想想這樣。你有2個清單:

lfoo = [] 
lbar = [] 

現在要各自追加添加到您的設置:

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

現在,當您爲組做哈希查找,你不能僅僅依靠函數部分的實例方法。的確,lfoolbar最終使用相同的功能(list.append)。所以這不是一個獨特的散列。你使它獨特的方式是將它附加到一個實例。但是,該實例不支持散列,因此該集合無法區分lfoo.appendlbar.append之間的區別。

+0

謝謝,更新了問題以參考 .append,而不是list.append –

2

在Python中,list對象不可散列。我懷疑當你散列一個實例方法時,它會合並它綁定的實例的散列。因此,您可以獲得TypeError

相關問題