Ответ 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
>>>
Я работаю над учебником на веб-сайте 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]
работает, и что именно происходит? Я никогда не видел этого раньше, кроме как для создания списков, и я не понимаю это концептуально.
Они могут сделать это, поскольку используют 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
>>>
Это работает, потому что объект, который они используют (в данном случае массив 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])
На самом деле он не работает в базовом Python (как ваш пример). Если вы запускаете свой код, Python генерирует исключение: "TypeError: индексы списка должны быть целыми или кусочками, а не кортежем".
1, 1
, переданный в board
, интерпретируется как кортеж, и поскольку доска должна быть проиндексирована целыми числами или слайсами, это не сработает.
Однако, если бы board
был некоторый тип структуры данных, подобной массиву, и разработчик внедрил поддержку индексации с кортежами, это работало бы. Примером этого являются массивы в numpy
.
Синтаксис 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)
, и обычные списки не могут работать с кортежами в качестве значения индексации.
Потому что их board
это либо numpy.ndarray
, либо какой-то другой тип, который его оборачивает, например pandas.DataFrame
Вы должны были сделать type(board)
. Или покажите нам строки, которые создают и инициализируют board
.
Кроме того, когда вы говорите "когда я запускаю программу, все идет как положено", вы должны работать в интерактивном режиме (python -i
), тогда вы можете запускать такие запросы, как type(board)
В 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]