Je travaille sur un tutoriel sur le site GeekforGeeks et j'ai remarqué qu'ils vérifient un point dans un tableau en utilisant board[x,y]
, que je n'ai jamais vu auparavant. Je ne pense pas que cela fonctionnerait, mais lorsque j'exécute le programme, tout se passe comme prévu.
J'ai essayé d'exécuter un exemple de code plus petit en utilisant leur méthode décrite ci-dessus par rapport à la méthode que je connais mieux (board[x][y]
), mais lorsque j'exécute mon code, j'obtiens TypeError: list indices must be integers or slices, not Tuple
Mon code:
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)
Leur code:
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)
Quelqu'un peut-il m'expliquer pourquoi board[x,y]
fonctionne, et que se passe-t-il exactement? Je n'ai jamais vu cela auparavant, sauf pour créer des listes, et je ne le saisis pas conceptuellement.
Ils sont capables de le faire car ils utilisent NumPy, ce qui ne générera pas d'erreur.
>>> 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
>>>
Cela fonctionne car l'objet qu'ils utilisent (dans ce cas, le tableau numpy) surcharge le __getitem__
méthode. Voir cet exemple de jouet:
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])
Il ne fonctionne pas réellement dans la base Python (comme votre exemple). Si vous exécutez votre code, Python lève une exception: 'TypeError: les index de liste doivent être entiers ou tranches, pas Tuple '.
Le 1, 1
passé à board
est interprété comme un tuple et comme la carte doit être indexée avec des entiers ou des tranches, cela ne fonctionnera pas.
Cependant, si board
était un type de structure de données de type tableau et que le développeur avait implémenté la prise en charge de l'indexation avec des tuples, cela fonctionnerait. Un exemple de ceci est les tableaux dans numpy
.
La syntaxe board[x, y]
Est probablement appliquée à un tableau numpy, qui accepte cette syntaxe afin d'implémenter des opérations de découpage indexées ligne/colonne. Jetez un œil à ces exemples:
>>> 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]])
Bien sûr, écrire my_list[x, y]
Génère une erreur car x, y
Est en fait un tuple (x, y)
, Et les listes régulières ne peuvent pas fonctionner avec des tuples comme valeur d'indexation.
Parce que leur board
est soit numpy.ndarray
Soit un type qui l'enveloppe, par exemple pandas.DataFrame
board[x,y]
Est pandas Indexation 2D, pas Python de base.
Vous auriez dû faire type(board)
. Ou montrez-nous les lignes qui créent et initialisent board
.
En outre, lorsque vous dites "lorsque j'exécute le programme, tout se passe comme prévu", vous devez exécuter en mode interactif (python -i
), Puis vous pouvez exécuter des requêtes comme type(board)
(ou dans iPython/jupyter type whos
pour voir la liste des variables et leurs types)
En python, []
est __getitem__
, qui peut être facilement réécrit.
Et, 1, 2
in python nous donnera un Tuple. oui, nous n'avons pas vraiment besoin de ()
pour créer un Tuple non vide.
Donc, Numpy peut le faire très facilement, même moi.
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
Vous pouvez utiliser le code ci-dessous pour essayer votre propre 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]