2012-04-02 200 views
3

我注意到operator.itemgetter對象沒有定義__eq__,所以它們的比較默認爲檢查標識(is)。比較itemgetter對象

將兩個itemgetter實例定義爲平等,每當它們的初始化參數列表比較爲相等時,是否有任何缺點?

下面是這種比較的一個用例。假設您定義了一個有序的數據結構,其構造函數需要一個鍵函數來定義排序。假設您想檢查兩個這樣的數據結構是否具有相同的鍵功能(例如,在assert語句中;或者驗證它們是否可以安全合併等)。

這將是很好,如果我們可以肯定地回答這個問題,當兩個關鍵功能是itemgetter('id')。但目前,itemgetter('id') == itemgetter('id')將評估爲False

+0

我看不出這將是有益的...這說,看到'itemgetter'是在C中定義的,你可以共同攻擊一個類來覆蓋'__getitem__',然後運行這兩個getter來檢查是否訪問了同一個項目。這不是一個優雅或快速的解決方案,但我看不出如何做得更好。 – 2012-04-02 02:45:38

+0

@NiklasB。我更新了這個問題,爲此提供了動力。 – max 2012-04-02 02:53:06

+0

在這種情況下,我會使用'lambda'表達式。 – satoru 2012-04-02 02:56:34

回答

4

尼克拉斯的回答相當巧妙,但需要更強的條件爲itemgetter可以採取多個參數

from collections import defaultdict 
from operator import itemgetter 
from itertools import count 

def cmp_getters(ig1, ig2): 
    if any(not isinstance(x, itemgetter) for x in (ig1, ig2)): 
     return False 
    d1 = defaultdict(count().next) 
    d2 = defaultdict(count().next) 
    ig1(d1)         # populate d1 as a sideeffect 
    ig2(d2)         # populate d2 as a sideeffect 
    return d1==d2 

一些測試用例

>>> cmp_getters(itemgetter('foo'), itemgetter('bar')) 
False 
>>> cmp_getters(itemgetter('foo'), itemgetter('bar','foo')) 
False 
>>> cmp_getters(itemgetter('foo','bar'), itemgetter('bar','foo')) 
False 
>>> cmp_getters(itemgetter('bar','foo'), itemgetter('bar','foo')) 
True 
+0

這完全可以工作,但我實際上想知道'class itemgetter'是否應該實現這個功能(這顯然會容易得多,因爲它可以依賴於實例的內部狀態)。 – max 2012-04-02 06:10:23

+0

@max,以及itemgetter類在C中實現,所以你不能真正添加​​到它的功能,你可以提出一個pep雖然 – 2012-04-02 07:37:23

+0

FYI PEPs不需要這樣的小事情。 – 2012-04-02 10:50:47

0

itemgetter返回callable。我希望你不想比較可媲美。正確?因爲即使您傳遞相同的參數,返回的可調用標識也不會保持相同。

def fun(a): 
    def bar(b): 
     return a*b 
    return bar 

a = fun(10) 
print id(a(10)) 

a = fun(10) 
print id(a(10)) 

在另一方面,當使用itemgetter調用作爲訪問器來訪問基礎對象,則該對象的比較將被用於執行它在Sorting Howto using the operating module functions所示的比較 。

+2

我並不是想要比較* any * callable,我的意思是隻比較'itemgetter'實例(這實際上是可以調用的)!由於'itemgetter'的語義,他們似乎可以安全地根據初始化參數進行比較。我錯過了什麼? – max 2012-04-02 03:46:35