Python – есть ли способ реализовать __getitem__ для многомерного массива?

Я хотел бы использовать что-то вроде этого:

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

но, к несчастью, когда я звоню:

 board[x][y] 

Я получаю: TypeError: __getitem__() takes exactly 3 arguments (2 given)

4 Solutions collect form web for “Python – есть ли способ реализовать __getitem__ для многомерного массива?”

Когда вы делаете board[x][y] вы __getitem__ два вызова __getitem__ потому что вы выполняете два отдельных доступа: [x] – один, а [y] – другой. __getitem__ обработать это прямо в __getitem__ ; вы должны иметь board[x] вернуть какой-то под-объект, который вы могли бы использовать [y] для получения отдельного элемента. Вероятно, вы хотите, чтобы __getitem__ принимал кортеж:

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

Затем выполните:

 board[x, y] 

(Обратите внимание, что у вас есть порядок x и y, переключенный между __getitem__ и board[x][y] — это намеренно?)

Просто делать:

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

потому что, когда вы вызываете b[x][y] он на самом деле вызывает __getitem__() дважды, как показано ниже:

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

Но лучше всего было бы подклассифицировать np.ndarray , чтобы вам не пришлось повторно реализовывать этот метод:

 class Board(np.ndarray): pass 

board[x][y] означает board.__getitem__(x).__getitem__(y) , поэтому Board.__getitem__ должен возвращать какое-то представление, которое также поддерживает __getitem__ и запоминает x . Это немного работа, но для некоторых случаев использования (что-то, что связано с передачей этого вида), это очень удобно.

Другим вариантом является board[x, y] , что означает board.__getitem__((x, y)) . Обратите внимание, что это передает кортеж __getitem__ , который вам придется распаковывать вручную (для этого используется синтаксический сахар, чтобы сделать это в 2.x, но он немного неясен, а также ушел в 3.x, поэтому вы можете его избежать в интересах будущей работы по портированию).

Возможно, вы захотите использовать этот синтаксис:

 board[(x, y)] 

Он менее симпатичный, но он позволяет вам иметь многомерные массивы просто. Любое количество измерений:

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

Делая совет по умолчанию, вы даже можете иметь разреженные словари:

 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 

Если вы хотите что-то более продвинутое, чем вы, вероятно, хотите NumPy .

  • С socketserver python как передать переменную в конструктор класса обработчика
  • pyodbc не сообщает ошибку сервера sql
  • flake8 не собирает файл конфигурации
  • Python: доступ к информации внешнего процесса
  • Tkinter. Создание нескольких кнопок с «другой» функцией команды
  • Заменить все вхождения определенных слов
  • Как найти элементы соответствия из двух списков?
  • Что делает max в списке наборов?
  • Python - лучший язык программирования в мире.