Reputation: 1856
When nested lists encountered in a class (more specifically, I should call it a multivariate function), can I use __getitem__
method with two or more arguments?
I know it's not the typical usage of __getitem__
and I should write it as a method of class, but I really want to take advantage of its []
feature.
Upvotes: 1
Views: 115
Reputation: 8557
It's really not atypical at all; numpy does it all the time. __getitem__
accepts a single argument; it can be a tuple. You'll just have to parse the tuple yourself.
class Indexer(object):
def __init__(self, *args, **kwargs):
pass
def __getitem__(self, item):
if isinstance(item, tuple):
# do special processing for tuples here
print(item)
# Everyone likes the number 3, so make sure to return an extra 3.
return [item, 3]
i = Indexer()
# this will print (2, 3), and got_item will have the value [(2, 3), 3]
got_item = i[2,3]
# This will print [(2, 3), 3]
print(got_item)
Obviously there's no real reason to return [item, 3]
, but it just demonstrates that the code inside __getitem__
can do whatever it wants. You can return anything your heart desires.
Whenever the Python interpreter sees you index something (as in i[2, 3]
in the code sample), the first thing it does is build a tuple out of the stuff between the square brackets. You can check this by using the dis module, which disassembles python code to see what the interpreter is really doing:
import dis
dis.dis('a[b, c]')
1 0 LOAD_NAME 0 (a)
3 LOAD_NAME 1 (b)
6 LOAD_NAME 2 (c)
9 BUILD_TUPLE 2
12 BINARY_SUBSCR
13 RETURN_VALUE
If you've never seen output from dis before, it can be a little confusing. The important part is where it says BUILD_TUPLE
before it says BINARY_SUBSCR
.
That may be too much info: the important thing is that you can do whatever you want with __getitem__
.
Upvotes: 1
Reputation: 5210
__getitem__
accepts as many arguments as you want, as they are packed as a tuple. See the following example, where the nested list inside the class is stored in _data
and initialized using certain dimensions.
class Table(object):
def __init__(self, dimx, dimy, initialize=0):
self._dimx = dimx
self._dimy = dimy
self._data = [[initialize] * self._dimx] * self._dimy
def __getitem__(self, *args):
idx = args[0]
return self._data[idx[0]][idx[1]]
def __setitem__(self, *args):
idx = args[0]
self._data[idx[0]][idx[1]] = args[1]
With this class, you can simply perform the following:
t = Table(10, 1)
t[0, 1] = 'a'
print(t[0, 0])
print(t[0, 1])
... and it will yield:
0
a
Upvotes: 0