#python #arrays #getter-setter
Вопрос:
Я пытаюсь переопределить сеттер и украсить его, но не понимаю, как это работает для многомерного массива.
class Board:
def __init__(self):
self.board = []
for k in range(3):
self.board.append([0] * 3)
def __str__(self):
return 'n'.join([' '.join([str(num) for num in row]) for row in self.board])
def __repr__(self):
return self.__str__()
def __setitem__(self, item, value):
print(f'setting {item=}tt{value=}')
self.board[item] = value
def __getitem__(self, item):
print(f'getting {item=}')
return self.board[item]
Я обнаружил, что сеттер/геттер работает не так, как я ожидаю
>>> board = Board()
>>> print(board)
0 0 0
0 0 0
0 0 0
>>> print(board[1][1])
getting item=1
0
>>> board[1][1] = 3
getting item=1
Я ожидал, что сеттер будет работать здесь, но я думаю, что геттер возвращает список и изменяет элемент этого списка.
>>> print(board)
0 0 0
0 3 0
0 0 0
>>> board[0] = [1, 3, 1]
setting item=0 value=[1, 3, 1]
>>> print(board)
1 3 1
0 3 0
0 0 0
Сеттер работает только в том случае, если я использую не более 1 индекса.
Комментарии:
1.
board[1]
возвращает объект списка . Что вы и установили.2. Другими словами, причина
board[1]
, по которой возвращаетсяlist
объект, заключается в том, чтоself.board
это список списков .3. Верно. Когда вы звоните
board[1][1]
,board[1]
часть вызывает вашего получателя. Это возвращает обычный список Python, поэтому ваш второй[1]
код вообще не связан с вашим кодом. Если вы хотите использовать синтаксисboard[1,1]
, например numpy, то ваш сеттер получит кортеж, и вы будете полностью контролировать ситуацию.4. Итак, я должен использовать синтаксис «board[1,1]», если я не хочу добавлять другой класс для отдельных строк?
5. Очень важно отметить, что это вообще не массив, а значит, не многомерный массив. Это список
Ответ №1:
Я думаю,что было бы проще делать что-то, используя словарь значений вместо списка списков значений. В этом случае то, что вы назвали item
аргументом методов __setitem__()
и __getitem__()
, было переименовано indices
в приведенном ниже примере кода, так как теперь tuple
оно имеет целочисленные значения: (row, col)
.
class Board:
H, W = 3, 3 # Size in rows (height) X columns (width).
def __init__(self):
self.board = {(row, col): 0 for col in range(self.H)
for row in range(self.W)}
def __str__(self):
return 'n'.join(', '.join(str(self[row, col])
for col in range(self.H))
for row in range(self.W))
__repr__ = __str__
def __setitem__(self, indices, value):
self.board[indices] = value
def __getitem__(self, indices):
return self.board[indices]
if __name__ == '__main__':
board = Board()
print(board)
print(f'{board[1, 2]=}')
print()
board[1, 2] = 3
print(f'{board[1, 2]=}')
print(board)
Выход:
0, 0, 0
0, 0, 0
0, 0, 0
board[1, 2]=0
board[1, 2]=3
0, 0, 0
0, 0, 3
0, 0, 0