的Python:通过itemgetter(返回)不工作作为预期类

问题描述:

operator.itemgetter()函数的功能是这样的:的Python:通过itemgetter(返回)不工作作为预期类

>>> import operator 
>>> getseconditem = operator.itemgetter(1) 
>>> ls = ['a', 'b', 'c', 'd'] 
>>> getseconditem(ls) 
'b' 

编辑我添加了这部分突出inconsitency

>>> def myitemgetter(item): 
...  def g(obj): 
...   return obj[item] 
...  return g 
>>> mygetseconditem = myitemgetter(1) 

现在,我有这个类

>>> class Items(object): 
...  second = getseconditem 
...  mysecond = mygetseconditem 
... 
...  def __init__(self, *items): 
...   self.items = items 
... 
...  def __getitem__(self, i): 
...   return self.items[i] 

访问的第二个项目,其索引工作

>>> obj = Items('a', 'b', 'c', 'd') 
>>> obj[1] 
>>> 'b' 

所以不会通过mysecond方法

>>> obj.mysecond() 
'b' 

但由于某些原因,访问它使用second()方法抛出一个异常

>>> obj.second() 
TypeError: itemgetter expected 1 arguments, got 0 

什么给了?

obj.second是函数getseconditem。一个函数,期望一个参数操作。既然你没有任何争论就打电话obj.second就会引发你提出的错误。为了解决这个问题,你可以做obj.second(obj.items)或定义second不同:

class Items(object): 
    def __init__(self, *items): 
     self.items = items 

    def __getitem__(self, i): 
     return self.items[i] 

    def second(self): 
     return getseconditem(self.items) 

编辑

很清楚你的意思,你编辑你的问题后。我认为这里发生的是因为getseconditem不是用户定义的函数它不会在访问obj.second时转换为方法。它只是保持一个功能。以下可以在docs找到:

注意,从功能对象(未结合或结合的 )方法对象的转变每个属性从 类或实例中检索时间发生。在某些情况下,一个富有成果的优化是 将该属性分配给本地变量并调用该局部变量。 另请注意,此转换仅适用于用户定义的 函数;其他可调用对象(以及所有不可调用对象) 未经转换即检索。

+0

从技术上讲,它被称为一种方法,它通常会自动作为一种自动选项。我的猜测是,以这种方式将函数附加到对象上会导致运行时将它视为“静态”方法。可能有一个装饰器可以用来强制它把它当作一种方法。 – Cyclone 2012-01-18 07:15:09

+0

@Rob Wouters:我想我的问题是什么让我的任务'mysecond = mygetseconditem'特别。为什么这个工作而另一个不工作? – 2012-01-18 07:33:57

+0

@mike,我编辑了我的答案,添加了我认为会导致差异的内容。 – 2012-01-18 08:04:03

问题似乎是以下几点:

>>> print (getseconditem, mygetseconditem) 
(<operator.itemgetter object at 0x01EE5BD0>, <function g at 0x00504DB0>) 

换句话说,函数可以被绑定,但可调用不能。

+0

这不起作用,因为'getseconditem'将会通过'class'而不是实例,因此不能访问'self.items'(或'self .__ getitem__')。 – 2012-01-18 07:24:20

+0

@ rob-wouters,好点!但问题似乎更深入。 – newtover 2012-01-18 08:04:51