Is there a way to implement __getitem__ for a multidimensional array?

I would like to use something like this:

class Board(): ... def __getitem__(self, y, x): return self.board[y][x] 

but unfortunately when I call:

 board[x][y] 

I get: TypeError: __getitem__() takes exactly 3 arguments (2 given)

+7
python arrays numpy multidimensional-array
source share
4 answers

When you execute board[x][y] , you will call two __getitem__ calls because you are doing two separate accesses: [x] one, and [y] other. There is no way to handle this directly in __getitem__ ; you must have board[x] return some kind of sub-object that you could use [y] to get a single item. You probably want __getitem__ accept a tuple:

 def __getitem__(self, tup): y, x = tup return self.board[y][x] 

Then do:

 board[x, y] 

(Note that you have an x ​​and y order that switches between __getitem__ and board[x][y] --- is this intentional?)

+8
source share

Just do:

 class Board(): def __getitem__(self, x): return self.board[x] 

because when you call b[x][y] , it actually calls __getitem__() twice, as shown below:

 import numpy as np b = Board() b.board = np.random.random((3,3,3)) print (b[2][0]==(b[2])[0]).all() #True 

But it would be best to subclass np.ndarray , so you do not need to np.ndarray this method:

 class Board(np.ndarray): pass 
+3
source share

board[x][y] means board.__getitem__(x).__getitem__(y) , so Board.__getitem__ should return some kind of view that also supports __getitem__ and remembers x . This is a little work, but for some use cases (anything related to conveying this view) it is very convenient.

Another option is board[x, y] , which means board.__getitem__((x, y)) . Note that this passes the tuple to __getitem__ , which you will have to unpack manually (it uses syntactic sugar for this in 2.x, but it is a bit obscure and also went to 3.x, so you might want to avoid this in the interests of the future porting work).

+2
source share

You might want to use this syntax:

 board[(x, y)] 

It is less pretty, but it allows you to have multidimensional arrays simply. Any number of measurements:

 board[(1,6,34,2,6)] 

By creating a defaultdict board, you can even have sparse dictionaries:

 board[(1,6,34,2,6)] >>> from collections import defaultdict >>> board = defaultdict(lambda: 0) >>> board[(1,6,8)] = 7 >>> board[(1,6,8)] 7 >>> board[(5,6,3)] 0 

If you need something more advanced than you probably want NumPy .

+1
source share

All Articles