I've created a Board
class for a connect 4 game that makes use of a list of lists. I'd like to have the object support indexing for both the rows and the columns of the board:
class Test:
def __init__(self, cols, rows):
self.cols = cols
self.rows = rows
self.data = [[' '] * cols for row in range(rows)]
def __iter__(self):
yield from self.data
def __getitem__(self, row):
pass
# what should this be?
I know I need to define __getitem__
but what should this method be to allow syntax such as b[1][1]
? I've taken a look at some past questions but I can't seem to find the answer I'm looking for.
Edit: maybe the following is the correct way to do things?
def __getitem__(self, row):
return self.data[row]
The fundamental thing you need to understand is that for syntax like b[1][2]
, there are two __getitem__
calls. First, b.__getitem__(1)
is called, and that returns an object. Then, returned_object.__getitem__(2)
is called. So, whatever class b
is does NOT have full control over this whole process.
In your example above, if you defined it as
def __getitem__(self, row):
return self.data[row]
then b[1][2]
would first call b.__getitem__(1)
, which would return self.data[1]
, which would be a list. That list also supports __getitem__
, and so next list.__getitem__(2)
would be called.
If you want control over both of those, then you need to define another class that represents columns, the parent class would need to return one of those objects instead of the raw list, and then that one can implement its own __getitem__
for custom functionality.
Other choice is to support syntax like b[1,2]
which is legal - it will call b.__getitem__((1,2))
with (1,2)
as a tuple (you can put anything in there really), but it's not as natural.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With