Есть ли разница между 'board [x, y]' и 'board [x] [y]' в Python?

Я работаю над учебником на веб-сайте GeekforGeeks и заметил, что они проверяют точку в массиве, используя board[x,y], чего я никогда раньше не видел. Я не думаю, что это сработает, но когда я запускаю программу, все идет как положено.

Я попытался запустить меньший пример кода, используя их метод, описанный выше, по сравнению с методом, с которым я более знаком (board[x][y]), но когда я запускаю свой код, я получаю TypeError: list indices must be integers or slices, not tuple

Мой код:

board = [[1,1,1], [1,2,2], [1,2,2]]
win = 'True'

if board[1][1] == 2:
    win = 'True by normal standards'
    print(win)
if board[1, 1] == 2:
    win = 'True by weird standards'
    print(win)

print(win)

Их код:

def row_win(board, player): 
    for x in range(len(board)): 
        win = True

        for y in range(len(board)): 
            if board[x, y] != player: 
                win = False
                continue

        if win == True: 
            return(win) 
    return(win) 

Может кто-нибудь объяснить мне, почему board[x,y] работает, и что именно происходит? Я никогда не видел этого раньше, кроме как для создания списков, и я не понимаю это концептуально.

Ответы

Ответ 1

Они могут сделать это, поскольку используют NumPy, что не приведет к ошибке.

>>> a = np.array([[1,1,1], [1,2,2], [1,2,2]])
>>> a[1,1]
2
>>> # equivalent to
>>> a = [[1,1,1], [1,2,2], [1,2,2]]
>>> a[1][1]
2
>>> 

Ответ 2

Это работает, потому что объект, который они используют (в данном случае массив numpy) перегружает метод __getitem__. Посмотрите этот пример с игрушкой:

class MyArray:
  def __init__(self, arr):
    self.arr = arr
  def __getitem__(self, t):
    return self.arr[t[0]][t[1]]

myarr = MyArray([[1,1,1], [1,2,2], [1,2,2]])
print(myarr[0,1])

Ответ 3

На самом деле он не работает в базовом Python (как ваш пример). Если вы запускаете свой код, Python генерирует исключение: "TypeError: индексы списка должны быть целыми или кусочками, а не кортежем".

1, 1, переданный в board, интерпретируется как кортеж, и поскольку доска должна быть проиндексирована целыми числами или слайсами, это не сработает.

Однако, если бы board был некоторый тип структуры данных, подобной массиву, и разработчик внедрил поддержку индексации с кортежами, это работало бы. Примером этого являются массивы в numpy.

Ответ 4

Синтаксис board[x, y], вероятно, применяется к пустому массиву, который принимает этот синтаксис для реализации индексированных операций среза строк/столбцов. Посмотрите на эти примеры:

>>> x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])  # creates 2D array
>>> x
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

>>> x[1]  # get second row (remember, index starts at 0)
array([4, 5, 6])

>>> x[:, 2]  # get third column
array([3, 6, 9])

>>> x[1, 2]  # get element on second row, third column
6

>>> x[1][2]  # same as before but with non-broadcasting syntax (i.e. works for lists as you are used to)
6

>>> x[1, 0:2]  # get first two elements of second row  
array([4, 5])

>>> x[0:2, 0:2]  # subsets the original array, "extracting" values from the first two columns/rows only
array([[1, 2],
       [4, 5]])

Конечно, написание my_list[x, y] выдает ошибку, потому что x, y на самом деле является кортежем (x, y), и обычные списки не могут работать с кортежами в качестве значения индексации.

Ответ 5

Потому что их board это либо numpy.ndarray, либо какой-то другой тип, который его оборачивает, например pandas.DataFrame

Вы должны были сделать type(board). Или покажите нам строки, которые создают и инициализируют board.

Кроме того, когда вы говорите "когда я запускаю программу, все идет как положено", вы должны работать в интерактивном режиме (python -i), тогда вы можете запускать такие запросы, как type(board)

Ответ 6

В python [] - это __getitem__, который можно легко переписать.

И 1, 2 в Python даст нам кортеж. да, нам не нужен () для создания непустого кортежа.

Таким образом, Numpy может сделать это очень легко, даже я могу.

In [1]: 1, 1
Out[1]: (1, 1)

In [2]: type(_)
Out[2]: tuple

In [3]: a = {(1, 1): 3}

In [4]: a[1, 1]
Out[4]: 3

In [5]: a[(1, 1)]
Out[5]: 3

In [6]: class NumpyArray(list):
   ...:     def __getitem__(self, index):
   ...:         if isinstance(index, tuple) and len(index) == 2:
   ...:             return self[index[0]][index[1]]
   ...:         return super().__getitem__(index)
   ...:

In [7]: b = NumpyArray([[0, 1], [2, 3]])

In [8]: b[1, 1]
Out[8]: 3

Вы можете использовать приведенный ниже код, чтобы попробовать свой собственный iPython.

class NumpyArray(list):
    def __getitem__(self, index):
        if isinstance(index, tuple) and len(index) == 2:
            return self[index[0]][index[1]]
        return super().__getitem__(index)

b = NumpyArray([[0, 1], [2, 3]])
b[1, 1]