【问题标题】:Why doesn't assigning a class to __getitem__ work?为什么为 __getitem__ 分配一个类不起作用?
【发布时间】:2019-02-13 22:33:03
【问题描述】:

这是一个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

【问题讨论】:

  • 隐式添加self作为第一个参数仅在从类中检索函数时发生。
  • 你用的是什么 Python 版本,这不是通常的 python 3 TypeError: toto() missing 1 required positional argument: 'thing' 也不是 python 2 TypeError: toto() takes exactly 2 arguments (1 given)
  • @BenoîtPilatte 这是 Windows 上的 3.6.2
  • @jasonharper 哦,完全有道理。这回答了我的问题。随意写下答案。
  • @jasonharper 不一定是函数,而是具有适当的 __get__ 方法(function 具有)的东西。

标签: python python-3.x class python-3.6


【解决方案1】:

函数可以用作方法,因为它具有__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__ 方法的对象。)

【讨论】:

猜你喜欢
  • 2013-03-21
  • 1970-01-01
  • 2012-09-08
  • 2010-11-12
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多