2012-04-02 153 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