首页 > 解决方案 > 为什么为 __getitem__ 分配一个类不起作用?

问题描述

这是一个list子类,它将其项目委托给itertools.compress.

from itertools import compress

class WeirdList(list):
    def __getitem__(self, item):
        return compress(self, item)

l = WeirdList([1, 2, 3, 4])
print(*l[0, 1, 0, 1]) # 2 4

以上工作正常,虽然我的印象是我可以直接分配compress__getitem__.

class WeirdList(list):
    __getitem__ = compress

l = WeirdList([1, 2, 3, 4])
print(*l[0, 1, 0, 1])

这引发了以下问题:

Traceback (most recent call last):
  File "...", line 7, in <module> print(*l[0, 1, 0, 1])
TypeError: Required argument 'selectors' (pos 2) not found

我相信这会中断,因为compress它是一个类而不是一个函数,但消息显示TypeError是从调用中引发的compress

什么时候__getitem__协议调用compress了一个参数?

标签: pythonpython-3.xclasspython-3.6

解决方案


函数可以用作方法,因为它具有__get__属性。该类没有属性compress__get__

>>> compress.__get__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module> 
AttributeError: type object 'itertools.compress' has no attribute '__get__'  

所以不能是一种方法。

使用__get__方法调用属性时,__get__会调用该方法并返回其返回值,而不是属性本身的值。也就是说,l[0] == l.__getitem__(0) == l.__getitem__.__get__(l, type(l))(0)的返回值__get__是一个已经l传递给函数的对象。

(如果您想知道装饰器classmethodstaticmethod装饰器的作用,它们会使用不同的__get__方法返回对象。)


推荐阅读