Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overloaded __getitem__ accepting another argument

I want to make the __getitem__ of one class be the sum of it and the item at the same index of another list.

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

However, my two attempts have resulted in errors:

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

Is it possible to give __getitem__ multiple arguments? If so, how? If not, is there a way to emulate it?

like image 809
rassar Avatar asked Oct 21 '25 01:10

rassar


1 Answers

It is possible because you get a tuple of "indices" in __getitem__ not multiple parameters:

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

There are some caveats however:

  • You need to explicitly call super().__getitem__ so you don't end up in an recursion.
  • You have to pay attention to the number of arguments passed to your __getitem__ if you want to allow normal slicing.
  • This behaviour will confuse users, so I wouldn't actually recommend using it!
like image 61
MSeifert Avatar answered Oct 22 '25 14:10

MSeifert