web-dev-qa-db-fra.com

Y a-t-il une différence entre `board [x, y]` et `board [x] [y]` en Python?

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.

46
Broski-AC

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
>>> 
44
U10-Forward

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])
11
Ant

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.

8
Grismar

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.

5
jfaccioni

Parce que leur board est soit numpy.ndarray Soit un type qui l'enveloppe, par exemple pandas.DataFrameboard[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)

5
smci

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]
2
LiuXiMin