Python:itemgetter() 返回的函数在类中行为异常

8 投票
2 回答
2611 浏览
提问于 2025-04-17 10:30

operator.itemgetter() 这个函数的工作原理是这样的:

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

编辑:我添加了这一部分来强调不一致性

>>> 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

这是怎么回事呢?

2 个回答

1

问题似乎出在以下内容:

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

换句话说,一个函数可以被绑定,但一个可调用的东西是不能的。

7

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 中找到:

请注意,从函数对象到(未绑定或绑定的)方法对象的转换发生在每次从类或实例中获取属性时。在某些情况下,一个有效的优化方法是将属性赋值给一个局部变量,然后调用这个局部变量。还要注意,这种转换只发生在用户定义的函数上;其他可调用对象(以及所有不可调用对象)在获取时不会进行转换。

撰写回答