重载__getitem__接受另一个参数

时间:2016-12-08 02:41:57

标签: python python-3.x overloading

我想让一个类的__getitem__为它的总和,以及另一个列表的相同索引处的项目。

>>> class Test(list):
    def __init__(self):
        self.extend([1, 2, 3])
    def __getitem__(self, index, other):
        return self[index] + other[index]
>>> t = Test()
>>> t2 = [4, 5, 6]

然而,我的两次尝试都导致错误:

>>> t[5, t2]
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    t[5, t2]
TypeError: __getitem__() missing 1 required positional argument: 'other'
>>> t.__getitem__(5, t2)
Traceback (most recent call last):
  File "<pyshell#26>", line 1, in <module>
    t.__getitem__(5, t2)
  File "<pyshell#17>", line 5, in __getitem__
    return self[index] + other[index]
TypeError: __getitem__() missing 1 required positional argument: 'other'

是否可以提供__getitem__多个参数?如果是这样,怎么样?如果没有,有没有办法模仿它?

2 个答案:

答案 0 :(得分:2)

这是可能的,因为你在__getitem__中得到一个“索引”元组而不是多个参数:

class Test(list):
    def __init__(self):
        self.extend([1, 2, 3])

    def __getitem__(self, value):
        # this makes sure that a sequence with exactly 2 elements is passed in: (thanks @ShadowRanger)
        index, other = value  
        return super().__getitem__(index) + other[index]

>>> t = Test()
>>> t2 = [4, 5, 6]
>>> t[2, t2]
9   # 3 + 6
>>> t[1, t2]
7   # 2 + 5
>>> t[0, t2]
5   # 1 + 4

但有一些警告:

  • 您需要明确调用super().__getitem__,这样才不会以递归方式结束。
  • 如果要允许正常切片,则必须注意传递给__getitem__的参数数量。
  • 这种行为会让用户感到困惑,所以我实际上并不推荐使用它!

答案 1 :(得分:1)

  

是否可以提供 getitem 多个参数?如果是这样,怎么样?如果没有,有没有办法模仿它?

为什么要模仿这个?你错过了&#34;魔术方法&#34;的重点。 Python为您提供了这些方法,以提供运算符重载的形式。以下是Python文档部分 3.3的摘录。特殊方法名称,描述了什么&#34;魔术方法&#34;用于:

  

类可以通过定义具有特殊名称的方法来实现由特殊语法(例如算术运算或下标和切片)调用的某些操作。 这是Python的运算符重载方法,允许类根据语言运算符定义自己的行为

(强调我的)

此外,这会使您的类对代码的读者不明确,这些读者希望__getitem__返回单个元素。

由于@MSeifert已经为您提供了实现所需行为的方法,因此我不会发布我的解决方案。但我强烈建议您创建自己的自定义方法。如果您仍然选择更改__getitem__方法的功能,我强烈建议您至少记录这些更改,并明确指出__getiem__的实现与正常实现的行为不同