J'ai besoin d'une bonne explication (les références sont un plus) sur la notation des tranches de Python.
Pour moi, cette notation a besoin d'être améliorée.
Elle semble extrêmement puissante, mais je n’ai pas encore réussi à la comprendre.
C'est assez simple, vraiment :
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
Il y a aussi la valeur step
, qui peut être utilisée avec n'importe lequel des éléments ci-dessus :
a[start:stop:step] # start through not past stop, by step
Le point clé à retenir est que la valeur :stop
représente la première valeur qui n'est pas dans la tranche sélectionnée. Ainsi, la différence entre stop
et start
est le nombre d'éléments sélectionnés (si step
est 1, la valeur par défaut).
L'autre caractéristique est que start
ou stop
peut être un nombre négatif, ce qui signifie qu'il compte à partir de la fin du tableau au lieu du début. Ainsi :
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
De même, step
peut être un nombre négatif :
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python est gentil avec le programmeur s'il y a moins d'éléments que ce que vous demandez. Par exemple, si vous demandez a[:-2]
et que a
ne contient qu'un seul élément, vous obtenez une liste vide au lieu d'une erreur. Parfois, vous préférez l'erreur, donc vous devez être conscient que cela peut arriver.
slice()
.L'opérateur de découpage en tranches []
est en fait utilisé dans le code ci-dessus avec un objet slice()
en utilisant la notation :
(qui n'est valide que dans []
), c'est-à-dire :
a[start:stop:step]
est équivalent à :
a[slice(start, stop, step)]
Les objets Slice se comportent aussi légèrement différemment selon le nombre d'arguments, de la même manière que range()
, c'est-à-dire que les deux slice(stop)
et slice(start, stop[, step])
sont supportés.
Pour ne pas spécifier un argument donné, on peut utiliser None
, de sorte que, par exemple, a[start :]
est équivalent à a[slice(start, None)]
ou a[::-1]
est équivalent à a[slice(None, None, -1)]
.
Bien que la notation basée sur :
soit très utile pour le découpage simple, l'utilisation explicite des objets slice()
simplifie la génération programmatique du découpage.
Le [tutoriel Python][1] en parle (faites défiler la page jusqu'à la partie concernant le découpage en tranches).
Le diagramme ASCII est également utile pour se souvenir du fonctionnement des tranches :
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
Une façon de se souvenir du fonctionnement des tranches est de penser que les indices pointent entre les caractères, le bord gauche du premier caractère étant numéroté 0. Le bord droit du dernier caractère d'une chaîne de n caractères a donc l'indice n.
[1] : http://docs.python.org/tutorial/introduction.html#strings
Enumération des possibilités permises par la grammaire :
>>> seq[:] # [seq[0], seq[1], ..., seq[-1] ]
>>> seq[low:] # [seq[low], seq[low+1], ..., seq[-1] ]
>>> seq[:high] # [seq[0], seq[1], ..., seq[high-1]]
>>> seq[low:high] # [seq[low], seq[low+1], ..., seq[high-1]]
>>> seq[::stride] # [seq[0], seq[stride], ..., seq[-1] ]
>>> seq[low::stride] # [seq[low], seq[low+stride], ..., seq[-1] ]
>>> seq[:high:stride] # [seq[0], seq[stride], ..., seq[high-1]]
>>> seq[low:high:stride] # [seq[low], seq[low+stride], ..., seq[high-1]]
Bien sûr, si (high-low)%stride != 0
, alors le point final sera un peu plus bas que high-1
.
Si stride
est négatif, l'ordre est un peu modifié puisque nous comptons vers le bas :
>>> seq[::-stride] # [seq[-1], seq[-1-stride], ..., seq[0] ]
>>> seq[high::-stride] # [seq[high], seq[high-stride], ..., seq[0] ]
>>> seq[:low:-stride] # [seq[-1], seq[-1-stride], ..., seq[low+1]]
>>> seq[high:low:-stride] # [seq[high], seq[high-stride], ..., seq[low+1]]
Les découpages étendus (avec virgules et ellipses) ne sont utilisés que par des structures de données spéciales (comme NumPy) ; les séquences de base ne les supportent pas.
>>> class slicee:
... def __getitem__(self, item):
... return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'