web-dev-qa-db-fra.com

Comprendre la notation de tranche

J'ai besoin d'une bonne explication (les références sont un plus) sur la notation slice de Python.

Pour moi, cette notation a besoin d'un peu de reprise.

Cela semble extrêmement puissant, mais je ne comprends pas trop bien.

2895
Simon

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 de ces choix:

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 non dans la tranche sélectionnée. Ainsi, la différence entre stop et start correspond au 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. Alors:

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 a ne contient qu'un seul élément, vous obtenez une liste vide au lieu d'une erreur. Parfois, vous préféreriez l'erreur, vous devez donc être conscient du fait que cela peut arriver.

Relation avec l'objet slice()

L’opérateur de découpage [] est actuellement utilisé dans le code ci-dessus avec un objet slice() utilisant la notation : (qui n’est valide que dans []):

a[start:stop:step]

est équivalent à:

a[slice(start, stop, step)]

Les objets Slice se comportent également légèrement différemment en fonction du nombre d’arguments, de la même façon que range(), c’est-à-dire que les deux slice(stop) et slice(start, stop[, step]) sont pris en charge. Pour ignorer la spécification d'un argument donné, vous pouvez 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 de découpage par programme.

3910
Greg Hewgill

Le tutoriel Python en parle (faites-le défiler un peu jusqu'à la partie concernant le découpage en tranches).

Le diagramme d’art ASCII est également utile pour rappeler le 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 rappeler le fonctionnement des tranches est de penser que les index pointent entre des caractères , le bord gauche du premier caractère étant numéroté 0. Puis le côté droit Le bord du dernier caractère d'une chaîne de n caractères a un index n .

504
Hans Nowak

Enumérant les 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 entendu, si (high-low)%stride != 0, le point final sera un peu inférieur à high-1.

Si stride est négatif, l'ordre est légèrement modifié car le compte à rebours est terminé:

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

Le découpage étendu (avec des virgules et des ellipses) est principalement utilisé uniquement par des structures de données spéciales (telles que 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)'
384
ephemient

Les réponses ci-dessus ne traitent pas de l'affectation des tranches. Pour comprendre l’attribution de tranche, il est utile d’ajouter un autre concept à l’art ASCII:

                +---+---+---+---+---+---+
                | P | y | t | h | o | n |
                +---+---+---+---+---+---+
Slice position: 0   1   2   3   4   5   6
Index position:   0   1   2   3   4   5

>>> p = ['P','y','t','h','o','n']
# Why the two sets of numbers:
# indexing gives items, not lists
>>> p[0]
 'P'
>>> p[5]
 'n'

# Slicing gives lists
>>> p[0:1]
 ['P']
>>> p[0:2]
 ['P','y']

Une heuristique consiste, pour une tranche de zéro à n, à penser: "zéro est le début, commence au début et prend n éléments dans une liste".

>>> p[5] # the last of six items, indexed from zero
 'n'
>>> p[0:5] # does NOT include the last item!
 ['P','y','t','h','o']
>>> p[0:6] # not p[0:5]!!!
 ['P','y','t','h','o','n']

Une autre heuristique est la suivante: "pour toute tranche, remplacez le début par zéro, appliquez la heuristique précédente pour obtenir la fin de la liste, puis comptez le premier chiffre sauvegardé pour couper les éléments du début"

>>> p[0:4] # Start at the beginning and count out 4 items
 ['P','y','t','h']
>>> p[1:4] # Take one item off the front
 ['y','t','h']
>>> p[2:4] # Take two items off the front
 ['t','h']
# etc.

La première règle d’attribution de tranche est la suivante: depuis le découpage renvoie une liste, l’affectation de tranche nécessite une liste (ou autre, répétable):

>>> p[2:3]
 ['t']
>>> p[2:3] = ['T']
>>> p
 ['P','y','T','h','o','n']
>>> p[2:3] = 't'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable

La deuxième règle d'attribution de tranche, que vous pouvez également voir ci-dessus, est que quelle que soit la partie de la liste renvoyée par l'indexation de tranche, il s'agit de la même partie que celle modifiée par l'attribution de tranche:

>>> p[2:4]
 ['T','h']
>>> p[2:4] = ['t','r']
>>> p
 ['P','y','t','r','o','n']

La troisième règle d'attribution de tranche est, la liste assignée (itérable) ne doit pas nécessairement avoir la même longueur; la tranche indexée est simplement découpée et remplacée en masse par ce qui est assigné:

>>> p = ['P','y','t','h','o','n'] # Start over
>>> p[2:4] = ['s','p','a','m']
>>> p
 ['P','y','s','p','a','m','o','n']

La partie la plus délicate à laquelle il faut s’habituer est l’affectation à des tranches vides. En utilisant l'heuristique 1 et 2, il est facile de se faire une idée indexation une tranche vide:

>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
 ['P','y','t','h']
>>> p[1:4]
 ['y','t','h']
>>> p[2:4]
 ['t','h']
>>> p[3:4]
 ['h']
>>> p[4:4]
 []

Et puis, une fois que vous avez vu cela, l'attribution de la tranche à la tranche vide a également un sens:

>>> p = ['P','y','t','h','o','n']
>>> p[2:4] = ['x','y'] # Assigned list is same length as slice
>>> p
 ['P','y','x','y','o','n'] # Result is same length
>>> p = ['P','y','t','h','o','n']
>>> p[3:4] = ['x','y'] # Assigned list is longer than slice
>>> p
 ['P','y','t','x','y','o','n'] # The result is longer
>>> p = ['P','y','t','h','o','n']
>>> p[4:4] = ['x','y']
>>> p
 ['P','y','t','h','x','y','o','n'] # The result is longer still

Notez que, puisque nous ne modifions pas le deuxième numéro de la tranche (4), les éléments insérés se superposent toujours au "o", même lorsque nous attribuons la tranche vide. Ainsi, la position pour l'affectation de tranche vide est l'extension logique des positions pour les affectations de tranche non vides.

Pour revenir un peu en arrière, que se passe-t-il lorsque vous continuez avec notre procession consistant à compter le début de la tranche?

>>> p = ['P','y','t','h','o','n']
>>> p[0:4]
 ['P','y','t','h']
>>> p[1:4]
 ['y','t','h']
>>> p[2:4]
 ['t','h']
>>> p[3:4]
 ['h']
>>> p[4:4]
 []
>>> p[5:4]
 []
>>> p[6:4]
 []

Avec le découpage en tranches, une fois que vous avez terminé, vous avez terminé; il ne commence pas à trancher en arrière. Dans Python, vous n'obtenez pas d'avancées négatives à moins que vous ne les demandiez explicitement en utilisant un nombre négatif.

>>> p[5:3:-1]
 ['n','o']

Il y a des conséquences étranges à la règle "une fois que vous avez terminé, vous avez terminé":

>>> p[4:4]
 []
>>> p[5:4]
 []
>>> p[6:4]
 []
>>> p[6]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

En fait, comparé à l'indexation, Python le découpage en tranches est étrangement infaillible:

>>> p[100:200]
 []
>>> p[int(2e99):int(1e99)]
 []

Cela peut être utile parfois, mais cela peut aussi conduire à un comportement quelque peu étrange:

>>> p
 ['P', 'y', 't', 'h', 'o', 'n']
>>> p[int(2e99):int(1e99)] = ['p','o','w','e','r']
>>> p
 ['P', 'y', 't', 'h', 'o', 'n', 'p', 'o', 'w', 'e', 'r']

En fonction de votre application, cela pourrait être ou ne pas être ce que vous espériez!


Ci-dessous le texte de ma réponse originale. Cela a été utile à beaucoup de gens, donc je ne voulais pas le supprimer.

>>> r=[1,2,3,4]
>>> r[1:1]
[]
>>> r[1:1]=[9,8]
>>> r
[1, 9, 8, 2, 3, 4]
>>> r[1:1]=['blah']
>>> r
[1, 'blah', 9, 8, 2, 3, 4]

Cela peut également clarifier la différence entre le découpage et l'indexation.

283
David M. Perlman

Expliquer la notation de tranche de Python

En bref, les deux points (:) en notation avec indice (subscriptable[subscriptarg]) créent une notation en tranches, qui comporte les arguments facultatifs, start, stop, step:

sliceable[start:stop:step]

Le découpage en python est un moyen informatique rapide d'accéder méthodiquement à certaines parties de vos données. À mon avis, pour être même un programmeur Python intermédiaire, il est nécessaire de se familiariser avec un aspect du langage.

Définitions importantes

Pour commencer, définissons quelques termes:

start: l’index de début de la tranche, il inclura l’élément à cet index sauf s’il est identique à stop , la valeur par défaut est 0, c'est-à-dire le premier index. Si c'est négatif, cela signifie de commencer n éléments à partir de la fin.

stop: l'index de fin de la tranche, cela fait not inclure l'élément à cet index, par défaut à la longueur de la séquence en cours de coupe, c'est-à-dire jusqu'à la fin.

étape: le montant par lequel l'index augmente augmente par défaut à 1. S'il est négatif, vous effectuez un découpage inversé de l'itéré.

Comment fonctionne l'indexation

Vous pouvez faire n'importe lequel de ces nombres positifs ou négatifs. La signification des nombres positifs est simple, mais pour les nombres négatifs, comme pour les index en Python, vous comptez à rebours à partir de la fin pour start et stop , et pour le step , vous décrémentez simplement votre index. Cet exemple est tiré du tutoriel de la documentation , mais je l'ai légèrement modifié pour indiquer l'élément de la séquence auquel chaque index fait référence:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5 
  -6  -5  -4  -3  -2  -1

Comment fonctionne le tranchage

Pour utiliser la notation de tranche avec une séquence qui la prend en charge, vous devez inclure au moins un signe deux-points dans les crochets qui suivent la séquence (qui réellement implémente la méthode __getitem__ de la séquence, selon la méthode Python modèle de données .)

La notation de tranche fonctionne comme ceci:

sequence[start:stop:step]

Et rappelez-vous qu'il existe des valeurs par défaut pour start , stop , et step , donc, pour accéder aux valeurs par défaut, laissez simplement de côté l’argument.

La notation par tranches pour obtenir les neuf derniers éléments d'une liste (ou de toute autre séquence qui la prend en charge, comme une chaîne) ressemblerait à ceci:

my_list[-9:]

Quand je vois cela, je lis la partie entre parenthèses comme "9ème de la fin, à la fin." (En fait, je l'abrévie mentalement en "-9, sur")

Explication:

La notation complète est

my_list[-9:None:None]

et pour substituer les valeurs par défaut (en fait, lorsque step est négatif, la valeur par défaut de stop est -len(my_list) - 1, donc None représente un arrêt qui signifie simplement qu'il passe à la dernière étape) :

my_list[-9:len(my_list):1]

Le deux-points , :, est ce qui indique à Python que vous lui attribuez une tranche et non un index régulier. C’est pourquoi la manière idiomatique de créer une copie superficielle des listes dans Python 2 est

list_copy = sequence[:]

Et les nettoyer est avec:

del my_list[:]

(Python 3 obtient une méthode list.copy et list.clear.)

Lorsque step est négatif, les valeurs par défaut de start et stop changent.

Par défaut, lorsque l'argument step est vide (ou None), il est attribué à +1.

Mais vous pouvez passer un entier négatif et la liste (ou la plupart des autres slicables standard) sera découpée de la fin au début.

Ainsi, une tranche négative modifiera les valeurs par défaut pour start et stop!

Confirmer cela dans le source

J'aime encourager les utilisateurs à lire le code source ainsi que la documentation. Le code source pour les objets slice et cette logique se trouve ici . Tout d'abord, nous déterminons si step est négatif:

 step_is_negative = step_sign < 0;

Si tel est le cas, la limite inférieure est -1, ce qui signifie que nous tranchons jusqu'au début et y compris le début, et la limite supérieure correspond à la longueur moins 1, ce qui signifie que nous commençons à la fin. (Notez que la sémantique de ce -1 est différent d'un -1 que les utilisateurs peuvent transmettre des index dans Python indiquant le dernier élément .)

if (step_is_negative) {
    lower = PyLong_FromLong(-1L);
    if (lower == NULL)
        goto error;

    upper = PyNumber_Add(length, lower);
    if (upper == NULL)
        goto error;
}

Sinon, step est positif et la limite inférieure sera zéro et la limite supérieure (que nous allons jusqu'à mais sans l'inclure) la longueur de la liste découpée en tranches.

else {
    lower = _PyLong_Zero;
    Py_INCREF(lower);
    upper = length;
    Py_INCREF(upper);
}

Ensuite, nous devrons peut-être appliquer les valeurs par défaut pour start et stop - la valeur par défaut pour start est alors calculée comme la limite supérieure lorsque step est négatif:

if (self->start == Py_None) {
    start = step_is_negative ? upper : lower;
    Py_INCREF(start);
}

et stop, la limite inférieure:

if (self->stop == Py_None) {
    stop = step_is_negative ? lower : upper;
    Py_INCREF(stop);
}

Donnez à vos tranches un nom descriptif!

Vous trouverez peut-être utile de séparer la découpe de la transmettre à la méthode list.__getitem__ ( c'est ce que font les crochets ). Même si vous n’êtes pas novice, le code reste plus lisible, ce qui permettra aux autres utilisateurs qui l’ont peut-être lue de comprendre plus facilement ce que vous faites.

Cependant, vous ne pouvez pas simplement assigner à une variable des entiers séparés par des deux points. Vous devez utiliser l'objet slice:

last_nine_slice = slice(-9, None)

Le deuxième argument, None, est requis pour que le premier argument soit interprété comme l'argument startsinon, il s'agirait de l'argument stop .

Vous pouvez ensuite passer l'objet slice à votre séquence:

>>> list(range(100))[last_nine_slice]
[91, 92, 93, 94, 95, 96, 97, 98, 99]

Il est intéressant de noter que les plages prennent également des tranches:

>>> range(100)[last_nine_slice]
range(91, 100)

Considérations sur la mémoire:

Comme les tranches de la liste Python créent de nouveaux objets en mémoire, une autre fonction importante à connaître est la itertools.islice. Généralement, vous souhaiterez effectuer une itération sur une tranche et non pas simplement la créer de manière statique en mémoire. islice est parfait pour cela. Une mise en garde, elle ne supporte pas les arguments négatifs pour start, stop, ou step, donc si c'est un problème, vous devrez peut-être calculer des index ou inverser l'itéré à l'avance.

length = 100
last_nine_iter = itertools.islice(list(range(length)), length-9, None, 1)
list_last_nine = list(last_nine_iter)

et maintenant:

>>> list_last_nine
[91, 92, 93, 94, 95, 96, 97, 98, 99]

Le fait que les tranches de liste fassent une copie est une caractéristique des listes elles-mêmes. Si vous découpez des objets avancés comme un Pandas DataFrame, il peut renvoyer une vue sur l'original et non une copie.

234
Aaron Hall

Et quelques choses qui n'étaient pas immédiatement évidentes pour moi quand j'ai vu la syntaxe de slicing pour la première fois:

>>> x = [1,2,3,4,5,6]
>>> x[::-1]
[6,5,4,3,2,1]

Un moyen facile d'inverser les séquences!

Et si vous vouliez, pour une raison quelconque, chaque deuxième élément de la séquence inversée:

>>> x = [1,2,3,4,5,6]
>>> x[::-2]
[6,4,2]
139
Dana

Dans Python 2.7

Trancher en Python

[a:b:c]

len = length of string, Tuple or list

c -- default is +1. The sign of c indicates forward or backward, absolute value of c indicates steps. Default is forward with step size 1. Positive means forward, negative means backward.

a --  When c is positive or blank, default is 0. When c is negative, default is -1.

b --  When c is positive or blank, default is len. When c is negative, default is -(len+1).

Comprendre l’affectation d’index est très important.

In forward direction, starts at 0 and ends at len-1

In backward direction, starts at -1 and ends at -len

Lorsque vous dites [a: b: c], vous dites, en fonction du signe de c (en avant ou en arrière), commencez par a et finissez par b (en excluant l'élément at bth index). Utilisez la règle d'indexation ci-dessus et souvenez-vous que vous ne trouverez que des éléments dans cette plage:

-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1

Mais cette gamme continue indéfiniment dans les deux sens:

...,-len -2 ,-len-1,-len, -len+1, -len+2, ..., 0, 1, 2,3,4 , len -1, len, len +1, len+2 , ....

Par exemple:

             0    1    2   3    4   5   6   7   8   9   10   11
             a    s    t   r    i   n   g
    -9  -8  -7   -6   -5  -4   -3  -2  -1

Si votre choix de a, b et c autorise un chevauchement avec la plage ci-dessus lorsque vous parcourez en utilisant les règles de a, b, c ci-dessus, vous obtiendrez une liste d'éléments (touchés lors du parcours) ou vous obtiendrez une liste vide.

Une dernière chose: si a et b sont égaux, alors vous obtenez également une liste vide:

>>> l1
[2, 3, 4]

>>> l1[:]
[2, 3, 4]

>>> l1[::-1] # a default is -1 , b default is -(len+1)
[4, 3, 2]

>>> l1[:-4:-1] # a default is -1
[4, 3, 2]

>>> l1[:-3:-1] # a default is -1
[4, 3]

>>> l1[::] # c default is +1, so a default is 0, b default is len
[2, 3, 4]

>>> l1[::-1] # c is -1 , so a default is -1 and b default is -(len+1)
[4, 3, 2]


>>> l1[-100:-200:-1] # Interesting
[]

>>> l1[-1:-200:-1] # Interesting
[4, 3, 2]


>>> l1[-1:-1:1]
[]


>>> l1[-1:5:1] # Interesting
[4]


>>> l1[1:-7:1]
[]

>>> l1[1:-7:-1] # Interesting
[3, 2]

>>> l1[:-2:-2] # a default is -1, stop(b) at -2 , step(c) by 2 in reverse direction
[4]
94
abc

Trouvé cette superbe table sur http://wiki.python.org/moin/MovingToPythonFromOtherLanguages

Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.

Index from rear:    -6  -5  -4  -3  -2  -1      a=[0,1,2,3,4,5]    a[1:]==[1,2,3,4,5]
Index from front:    0   1   2   3   4   5      len(a)==6          a[:5]==[0,1,2,3,4]
                   +---+---+---+---+---+---+    a[0]==0            a[:-2]==[0,1,2,3]
                   | a | b | c | d | e | f |    a[5]==5            a[1:2]==[1]
                   +---+---+---+---+---+---+    a[-1]==5           a[1:-1]==[1,2,3,4]
Slice from front:  :   1   2   3   4   5   :    a[-2]==4
Slice from rear:   :  -5  -4  -3  -2  -1   :
                                                b=a[:]
                                                b==[0,1,2,3,4,5] (shallow copy of a)
92
AdrianoFerrari

Après l’avoir utilisé un peu, je me rends compte que la description la plus simple est qu’il est exactement le même que les arguments d’une boucle for ...

(from:to:step)

N'importe lequel d'entre eux sont facultatifs:

(:to:step)
(from::step)
(from:to)

Ensuite, l'indexation négative nécessite simplement que vous ajoutiez la longueur de la chaîne aux index négatifs pour la comprendre.

Cela fonctionne pour moi quand même ...

59
Simon

Je trouve plus facile de me rappeler comment cela fonctionne, puis je peux comprendre toute combinaison spécifique de démarrage/arrêt/étape.

Il est instructif de comprendre range() en premier:

def range(start=0, stop, step=1):  # Illegal syntax, but that's the effect
    i = start
    while (i < stop if step > 0 else i > stop):
        yield i
        i += step

Commencer à partir de start, incrémenter de step, ne pas atteindre stop. Très simple.

La chose à retenir à propos de l’étape négative est que stop est toujours la fin exclue, qu’elle soit supérieure ou inférieure. Si vous voulez la même tranche dans l’ordre inverse, il est beaucoup plus propre de faire l’inversion séparément: par ex. 'abcde'[1:-2][::-1] coupe un caractère de la gauche, deux de la droite, puis l'inverse. (Voir aussi reversed() .)

Le découpage en séquence est identique, sauf qu'il normalise d'abord les index négatifs et qu'il ne peut jamais sortir de la séquence:

TODO: Le code ci-dessous présentait un bogue avec "ne jamais sortir de la séquence" lorsque abs (step)> 1; Je pense Je l'ai corrigé pour qu'il soit correct, mais c'est difficile à comprendre.

def this_is_how_slicing_works(seq, start=None, stop=None, step=1):
    if start is None:
        start = (0 if step > 0 else len(seq)-1)
    Elif start < 0:
        start += len(seq)
    if not 0 <= start < len(seq):  # clip if still outside bounds
        start = (0 if step > 0 else len(seq)-1)
    if stop is None:
        stop = (len(seq) if step > 0 else -1)  # really -1, not last element
    Elif stop < 0:
        stop += len(seq)
    for i in range(start, stop, step):
        if 0 <= i < len(seq):
            yield seq[i]

Ne vous inquiétez pas pour les détails de is None - rappelez-vous que le fait d'omettre start et/ou stop fait toujours le bon choix pour vous donner la séquence complète.

Normaliser d’abord les indices négatifs permet de compter indépendamment de start et/ou stop: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc' malgré range(1,-2) == []. La normalisation est parfois considérée comme "modulo la longueur", mais notez qu’elle n’ajoute la longueur qu’une seule fois: par ex. 'abcde'[-53:42] n'est que la chaîne entière.

46
Index:
      ------------>
  0   1   2   3   4
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
  0  -4  -3  -2  -1
      <------------

Slice:
    <---------------|
|--------------->
:   1   2   3   4   :
+---+---+---+---+---+
| a | b | c | d | e |
+---+---+---+---+---+
:  -4  -3  -2  -1   :
|--------------->
    <---------------|

J'espère que cela vous aidera à modéliser la liste en Python.

Référence: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages

37
xiaoyu

J'utilise moi-même la méthode "un index entre éléments", mais une façon de le décrire qui aide parfois les autres à l'obtenir est la suivante:

mylist[X:Y]

X est l'index du premier élément que vous voulez.
Y est l’indice du premier élément que vous ne voulez pas.

36
Steve Losh

Notation de découpage Python:

a[start:end:step]
  • Pour start et end, les valeurs négatives sont interprétées comme relatives à la fin de la séquence.
  • Les indices positifs pour end indiquent la position après le dernier élément à inclure.
  • Les valeurs vides sont définies par défaut comme suit: [+0:-0:1].
  • L'utilisation d'une étape négative inverse l'interprétation de start et end

La notation s'étend aux matrices (numpy) et aux tableaux multidimensionnels. Par exemple, pour découper des colonnes entières, vous pouvez utiliser:

m[::,0:2:] ## slice the first two columns

Les tranches contiennent des références, pas des copies, des éléments du tableau. Si vous voulez créer une copie séparée d'un tableau, vous pouvez utiliser deepcopy() .

35
nobar

Voici comment j'enseigne les tranches aux débutants:

Comprendre la différence entre l'indexation et le découpage en tranches:

Wiki Python a cette image étonnante qui distingue clairement l’indexation et le découpage en tranches.

enter image description here

C'est une liste avec 6 éléments. Pour mieux comprendre le découpage, considérez cette liste comme un ensemble de six cases placées ensemble. Chaque boîte contient un alphabet.

L'indexation est comme traiter avec le contenu de la boîte. Vous pouvez vérifier le contenu de n'importe quelle boîte. Mais vous ne pouvez pas vérifier le contenu de plusieurs boîtes à la fois. Vous pouvez même remplacer le contenu de la boîte. Mais vous ne pouvez pas placer 2 balles dans une boîte ou remplacer 2 balles à la fois.

In [122]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [123]: alpha
Out[123]: ['a', 'b', 'c', 'd', 'e', 'f']

In [124]: alpha[0]
Out[124]: 'a'

In [127]: alpha[0] = 'A'

In [128]: alpha
Out[128]: ['A', 'b', 'c', 'd', 'e', 'f']

In [129]: alpha[0,1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-129-c7eb16585371> in <module>()
----> 1 alpha[0,1]

TypeError: list indices must be integers, not Tuple

Trancher, c'est comme traiter avec les boîtes elles-mêmes. Vous pouvez ramasser la première boîte et la placer sur une autre table. Pour ramasser la boîte, tout ce que vous devez savoir est la position de début et de fin de la boîte.

Vous pouvez même ramasser les 3 premières boîtes ou les 2 dernières boîtes ou toutes les boîtes de 1 à 4. Ainsi, vous pouvez choisir n’importe quel jeu de boîtes si vous connaissez le début et la fin. Ces positions sont appelées positions start & stop.

La chose intéressante est que vous pouvez remplacer plusieurs boîtes à la fois. Aussi, vous pouvez placer plusieurs boîtes où vous le souhaitez.

In [130]: alpha[0:1]
Out[130]: ['A']

In [131]: alpha[0:1] = 'a'

In [132]: alpha
Out[132]: ['a', 'b', 'c', 'd', 'e', 'f']

In [133]: alpha[0:2] = ['A', 'B']

In [134]: alpha
Out[134]: ['A', 'B', 'c', 'd', 'e', 'f']

In [135]: alpha[2:2] = ['x', 'xx']

In [136]: alpha
Out[136]: ['A', 'B', 'x', 'xx', 'c', 'd', 'e', 'f']

Découper avec l'étape:

Jusqu'à présent, vous avez choisi des boîtes en continu. Mais certaines fois, vous devez ramasser discrètement. Par exemple, vous pouvez ramasser toutes les deux boîtes. Vous pouvez même ramasser chaque troisième case à partir de la fin. Cette valeur s'appelle step size. Cela représente l’écart entre Vos micros successifs. Le pas doit être positif si vous choisissez des boîtes du début à la fin, et inversement.

In [137]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [142]: alpha[1:5:2] 
Out[142]: ['b', 'd']

In [143]: alpha[-1:-5:-2]
Out[143]: ['f', 'd']

In [144]: alpha[1:5:-2]
Out[144]: []

In [145]: alpha[-1:-5:2]      
Out[145]: []

Comment Python détermine les paramètres manquants:

Si vous omettez un paramètre lors du découpage, Python essaie de le comprendre automatiquement.

Si vous vérifiez le code source de CPython, vous trouverez une fonction appelée PySlice_GetIndicesEx qui calcule les indices d'une tranche pour tout paramètre donné. Voici le code équivalent logique en Python.

Cette fonction prend un objet Python et des paramètres facultatifs pour le découpage en tranches et renvoie la longueur de début, d'arrêt, de pas et de tranche pour la tranche demandée.

def py_slice_get_indices_ex(obj, start=None, stop=None, step=None):

    length = len(obj)

    if step is None:
        step = 1
    if step == 0:
        raise Exception("Step cannot be zero.")

    if start is None:
        start = 0 if step > 0 else length - 1
    else:
        if start < 0:
            start += length
        if start < 0:
            start = 0 if step > 0 else -1
        if start >= length:
            start = length if step > 0 else length - 1

    if stop is None:
        stop = length if step > 0 else -1
    else:
        if stop < 0:
            stop += length
        if stop < 0:
            stop = 0 if step > 0 else -1
        if stop >= length:
            stop = length if step > 0 else length - 1

    if (step < 0 and stop >= start) or (step > 0 and start >= stop):
        slice_length = 0
    Elif step < 0:
        slice_length = (stop - start + 1)/(step) + 1
    else:
        slice_length = (stop - start - 1)/(step) + 1

    return (start, stop, step, slice_length)

C'est l'intelligence qui est présente derrière les tranches. Puisque Python a une fonction intégrée appelée slice, vous pouvez transmettre certains paramètres et vérifier son calcul intelligent des paramètres manquants.

In [21]: alpha = ['a', 'b', 'c', 'd', 'e', 'f']

In [22]: s = slice(None, None, None)

In [23]: s
Out[23]: slice(None, None, None)

In [24]: s.indices(len(alpha)) 
Out[24]: (0, 6, 1)

In [25]: range(*s.indices(len(alpha)))
Out[25]: [0, 1, 2, 3, 4, 5]

In [26]: s = slice(None, None, -1) 

In [27]: range(*s.indices(len(alpha)))
Out[27]: [5, 4, 3, 2, 1, 0]

In [28]: s = slice(None, 3, -1)        

In [29]: range(*s.indices(len(alpha)))
Out[29]: [5, 4]

Remarque: Cet article a été écrit à l'origine dans mon blog http://www.avilpage.com/2015/03/a-slice- of-python-intelligence-behind.html

32
ChillarAnand

Vous pouvez également utiliser l’affectation de tranche pour supprimer un ou plusieurs éléments d’une liste:

r = [1, 'blah', 9, 8, 2, 3, 4]
>>> r[1:4] = []
>>> r
[1, 2, 3, 4]
32
dansalmo

Ceci est juste pour quelques informations supplémentaires ... Considérez la liste ci-dessous

>>> l=[12,23,345,456,67,7,945,467]

Quelques autres astuces pour inverser la liste:

>>> l[len(l):-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[len(l)::-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[::-1]
[467, 945, 7, 67, 456, 345, 23, 12]

>>> l[-1:-len(l)-1:-1]
[467, 945, 7, 67, 456, 345, 23, 12]
31

En règle générale, écrire du code avec un grand nombre de valeurs d'index codées en dur entraîne des problèmes de lisibilité et de maintenance. Par exemple, si vous revenez au code un an plus tard, vous le consulterez et vous demanderez ce que vous pensiez au moment de l’écrire. La solution présentée est simplement un moyen d’exprimer plus clairement ce que votre code est en train de faire. En général, la fonction intégrée slice () crée un objet tranche qui peut être utilisé partout où une tranche est autorisée. Par exemple:

>>> items = [0, 1, 2, 3, 4, 5, 6]
>>> a = slice(2, 4)
>>> items[2:4]
[2, 3]
>>> items[a]
[2, 3]
>>> items[a] = [10,11]
>>> items
[0, 1, 10, 11, 4, 5, 6]
>>> del items[a]
>>> items
[0, 1, 4, 5, 6]

Si vous avez une instance de tranche s, vous pouvez obtenir plus d'informations à ce sujet en consultant ses attributs s.start, s.stop et s.step, respectivement. Par exemple:

>>> a = slice(10, 50, 2)
>>> a.start
10
>>> a.stop
50
>>> a.step
2
>>>
27
Python_Dude

1. Notation de tranche

Pour simplifier, rappelez-vous la tranche n'a qu'un seul formulaire:

s[start:end:step]

et voici comment cela fonctionne:

  • s: un objet pouvant être découpé
  • start: premier index pour commencer l'itération
  • end: dernier index, NOTE: end index ne sera pas inclus dans la tranche obtenue
  • step: élément de sélection tous les step index

Une autre chose à importer: tous start, end, step peuvent être omis! Et s'ils sont omis, leur valeur par défaut sera utilisée: 0, len(s), 1 en conséquence.

Donc, les variations possibles sont:

# mostly used variations
s[start:end]
s[start:]
s[:end]

# step related variations
s[:end:step]
s[start::step]
s[::step]

# make a copy
s[:]

NOTE: Si start>=end (en prenant en compte que lorsque step>0), python retournera une tranche vide [].

2. Pièges

La partie ci-dessus explique les fonctionnalités de base sur le fonctionnement de slice, cela fonctionnera dans la plupart des cas. Cependant, vous devez faire attention aux pièges, et cette partie les explique.

Indices négatifs

La toute première chose qui trouble python apprenants est que l'index peut être négatif! Ne paniquez pas: index négatif signifie compter à rebours.

Par exemple:

s[-5:]    # start at the 5th index from the end of array, 
          # thus returns the last 5 elements
s[:-5]    # start at index 0, end until the 5th index from end of array, 
          # thus returns s[0:len(s)-5]

Étape négative

Rendre les choses plus confuses est que step peut être négatif aussi!

ne étape négative signifie une nouvelle itération du tableau: de bout en bout, avec l'index de fin inclus et l'index de début exclu du résultat.

NOTE: lorsque step est négatif, la valeur par défaut pour start à len(s) (alors que end n'est pas égal à 0, car s[::-1] contient s[0]). Par exemple:

s[::-1]            # reversed slice
s[len(s)::-1]      # same as above, reversed slice
s[0:len(s):-1]     # empty list

Erreur hors plage?

Soyez surpris: la tranche ne déclenche pas IndexError lorsque l'index est hors de portée!

Si l'index est en dehors de la plage, python essayera de le mieux définir l'index sur 0 ou len(s) en fonction de la situation. Par exemple:

s[:len(s)+5]      # same as s[:len(s)]
s[-len(s)-5::]    # same as s[0:]
s[len(s)+5::-1]   # same as s[len(s)::-1], same as s[::-1]

3. exemples

Terminons cette réponse par des exemples expliquant tout ce dont nous avons discuté:

# create our array for demonstration
In [1]: s = [i for i in range(10)]

In [2]: s
Out[2]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [3]: s[2:]   # from index 2 to last index
Out[3]: [2, 3, 4, 5, 6, 7, 8, 9]

In [4]: s[:8]   # from index 0 up to index 8
Out[4]: [0, 1, 2, 3, 4, 5, 6, 7]

In [5]: s[4:7]  # from index 4(included) up to index 7(excluded)
Out[5]: [4, 5, 6]

In [6]: s[:-2]  # up to second last index(negative index)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7]

In [7]: s[-2:]  # from second last index(negative index)
Out[7]: [8, 9]

In [8]: s[::-1] # from last to first in reverse order(negative step)
Out[8]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

In [9]: s[::-2] # all odd numbers in reversed order
Out[9]: [9, 7, 5, 3, 1]

In [11]: s[-2::-2] # all even numbers in reversed order
Out[11]: [8, 6, 4, 2, 0]

In [12]: s[3:15]   # end is out of range, python will set it to len(s)
Out[12]: [3, 4, 5, 6, 7, 8, 9]

In [14]: s[5:1]    # start > end, return empty list
Out[14]: []

In [15]: s[11]     # access index 11(greater than len(s)) will raise IndexError
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]

IndexError: list index out of range
26
cizixs

Les réponses ci-dessus ne traitent pas du découpage multidimensionnel de tableaux, qui est possible à l'aide du fameux paquet NumPy:

Le découpage en tranches peut également être appliqué à des tableaux multidimensionnels.

# Here, a is a NumPy array

>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])
>>> a[:2, 0:3:2]
array([[1, 3],
       [5, 7]])

Le ":2" avant la virgule agit sur la première dimension et le "0:3:2" après la virgule agit sur la deuxième dimension.

20
Statham

Mon cerveau semble content d’accepter que lst[start:end] contienne le start- ème élément. Je pourrais même dire que c'est une "hypothèse naturelle".

Mais parfois, un doute s'installe et mon cerveau me demande de m'assurer qu'il ne contient pas le end- ème élément.

Dans ces moments, je m'appuie sur ce théorème simple:

for any n,    lst = lst[:n] + lst[n:]

Cette jolie propriété me dit que lst[start:end] ne contient pas l'item end- parce qu'il se trouve dans lst[end:].

Notez que ce théorème est vrai pour tout n du tout. Par exemple, vous pouvez vérifier que

lst = range(10)
lst[:-42] + lst[-42:] == lst

renvoie True.

14
Robert
#!/usr/bin/env python

def slicegraphical(s, lista):

    if len(s) > 9:
        print """Enter a string of maximum 9 characters,
    so the printig would looki Nice"""
        return 0;
    # print " ",
    print '  '+'+---' * len(s) +'+'
    print ' ',
    for letter in s:
        print '| {}'.format(letter),
    print '|'
    print " ",; print '+---' * len(s) +'+'

    print " ",
    for letter in range(len(s) +1):
        print '{}  '.format(letter),
    print ""
    for letter in range(-1*(len(s)), 0):
        print ' {}'.format(letter),
    print ''
    print ''


    for triada in lista:
        if len(triada) == 3:
            if triada[0]==None and triada[1] == None and triada[2] == None:
                # 000
                print s+'[   :   :   ]' +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] == None and triada[1] == None and triada[2] != None:
                # 001
                print s+'[   :   :{0:2d} ]'.format(triada[2], '','') +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] == None and triada[1] != None and triada[2] == None:
                # 010
                print s+'[   :{0:2d} :   ]'.format(triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] == None and triada[1] != None and triada[2] != None:
                # 011
                print s+'[   :{0:2d} :{1:2d} ]'.format(triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] != None and triada[1] == None and triada[2] == None:
                # 100
                print s+'[{0:2d} :   :   ]'.format(triada[0]) +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] != None and triada[1] == None and triada[2] != None:
                # 101
                print s+'[{0:2d} :   :{1:2d} ]'.format(triada[0], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] != None and triada[1] != None and triada[2] == None:
                # 110
                print s+'[{0:2d} :{1:2d} :   ]'.format(triada[0], triada[1]) +' = ', s[triada[0]:triada[1]:triada[2]]
            Elif triada[0] != None and triada[1] != None and triada[2] != None:
                # 111
                print s+'[{0:2d} :{1:2d} :{2:2d} ]'.format(triada[0], triada[1], triada[2]) +' = ', s[triada[0]:triada[1]:triada[2]]

        Elif len(triada) == 2:
            if triada[0] == None and triada[1] == None:
                # 00
                print s+'[   :   ]    ' + ' = ', s[triada[0]:triada[1]]
            Elif triada[0] == None and triada[1] != None:
                # 01
                print s+'[   :{0:2d} ]    '.format(triada[1]) + ' = ', s[triada[0]:triada[1]]
            Elif triada[0] != None and triada[1] == None:
                # 10
                print s+'[{0:2d} :   ]    '.format(triada[0]) + ' = ', s[triada[0]:triada[1]]
            Elif triada[0] != None and triada[1] != None:
                # 11
                print s+'[{0:2d} :{1:2d} ]    '.format(triada[0],triada[1]) + ' = ', s[triada[0]:triada[1]]

        Elif len(triada) == 1:
            print s+'[{0:2d} ]        '.format(triada[0]) + ' = ', s[triada[0]]


if __== '__main__':
    # Change "s" to what ever string you like, make it 9 characters for
    # better representation.
    s = 'COMPUTERS'

    # add to this list different lists to experement with indexes
    # to represent ex. s[::], use s[None, None,None], otherwise you get an error
    # for s[2:] use s[2:None]

    lista = [[4,7],[2,5,2],[-5,1,-1],[4],[-4,-6,-1], [2,-3,1],[2,-3,-1], [None,None,-1],[-5,None],[-5,0,-1],[-5,None,-1],[-1,1,-2]]

    slicegraphical(s, lista)

Vous pouvez exécuter ce script et l'essayer. Vous trouverez ci-dessous des exemples que j'ai obtenus à partir du script.

  +---+---+---+---+---+---+---+---+---+
  | C | O | M | P | U | T | E | R | S |
  +---+---+---+---+---+---+---+---+---+
  0   1   2   3   4   5   6   7   8   9   
 -9  -8  -7  -6  -5  -4  -3  -2  -1 

COMPUTERS[ 4 : 7 ]     =  UTE
COMPUTERS[ 2 : 5 : 2 ] =  MU
COMPUTERS[-5 : 1 :-1 ] =  UPM
COMPUTERS[ 4 ]         =  U
COMPUTERS[-4 :-6 :-1 ] =  TU
COMPUTERS[ 2 :-3 : 1 ] =  MPUT
COMPUTERS[ 2 :-3 :-1 ] =  
COMPUTERS[   :   :-1 ] =  SRETUPMOC
COMPUTERS[-5 :   ]     =  UTERS
COMPUTERS[-5 : 0 :-1 ] =  UPMO
COMPUTERS[-5 :   :-1 ] =  UPMOC
COMPUTERS[-1 : 1 :-2 ] =  SEUM
[Finished in 0.9s]

Lorsque vous utilisez une étape négative, notez que la réponse est décalée de 1 vers la droite.

14
mahmoh

En Python, la forme de base pour le découpage est la suivante:

l[start:end]

l est une collection, start est un index inclusif et end est un index exclusif.

In [1]: l = list(range(10))

In [2]: l[:5] # first five elements
Out[2]: [0, 1, 2, 3, 4]

In [3]: l[-5:] # last five elements
Out[3]: [5, 6, 7, 8, 9]

Lorsque vous découpez depuis le début, vous pouvez omettre l'index zéro et, lorsque vous découpez jusqu'à la fin, vous pouvez omettre l'index final car il est redondant, ne soyez donc pas commenté:

In [5]: l[:3] == l[0:3]
Out[5]: True

In [6]: l[7:] == l[7:len(l)]
Out[6]: True

Les entiers négatifs sont utiles lorsque vous effectuez des décalages par rapport à la fin d'une collection:

In [7]: l[:-1] # include all elements but the last one
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8]

In [8]: l[-3:] # take the last 3 elements
Out[8]: [7, 8, 9]

Il est possible de fournir des index hors limites lors du découpage, tels que:

In [9]: l[:20] # 20 is out of index bounds, l[20] will raise an IndexError exception
Out[9]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [11]: l[-20:] # -20 is out of index bounds, l[-20] will raise an IndexError exception
Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

N'oubliez pas que le découpage d'une collection produit une toute nouvelle collection. De plus, lors de l'utilisation de la notation de tranche dans les assignations, il n'est pas nécessaire que la longueur de l'affectation de tranche soit la même. Les valeurs avant et après la tranche attribuée seront conservées et la collection sera réduite ou agrandie pour contenir les nouvelles valeurs:

In [16]: l[2:6] = list('abc') # assigning less elements than the ones contained in the sliced collection l[2:6]

In [17]: l
Out[17]: [0, 1, 'a', 'b', 'c', 6, 7, 8, 9]

In [18]: l[2:5] = list('hello') # assigning more elements than the ones contained in the sliced collection l [2:5]

In [19]: l
Out[19]: [0, 1, 'h', 'e', 'l', 'l', 'o', 6, 7, 8, 9]

Si vous omettez les index de début et de fin, vous en ferez une copie:

In [14]: l_copy = l[:]

In [15]: l == l_copy and l is not l_copy
Out[15]: True

Si les index de début et de fin sont omis lors de l'exécution d'une opération d'affectation, l'intégralité du contenu de la collection sera remplacée par une copie de ce qui est référencé:

In [20]: l[:] = list('hello...')

In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']

Outre le découpage de base, il est également possible d'appliquer la notation suivante:

l[start:end:step]

l est une collection, start est un index inclusif, end est un index exclusif et step est une foulée qui peut être utilisée pour chaque caractère nth élément dans l.

In [22]: l = list(range(10))

In [23]: l[::2] # take the elements which indexes are even
Out[23]: [0, 2, 4, 6, 8]

In [24]: l[1::2] # take the elements which indexes are odd
Out[24]: [1, 3, 5, 7, 9]

Utiliser step fournit une astuce utile pour inverser une collection en Python:

In [25]: l[::-1]
Out[25]: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Il est également possible d'utiliser des entiers négatifs pour step comme exemple suivant:

In[28]:  l[::-2]
Out[28]: [9, 7, 5, 3, 1]

Cependant, utiliser une valeur négative pour step pourrait devenir très déroutant. De plus, pour être Pythonic, vous devez éviter d'utiliser start, end et step dans une seule tranche. Si cela est nécessaire, envisagez de le faire en deux assignations (une pour couper, et l'autre pour marcher).

In [29]: l = l[::2] # this step is for striding

In [30]: l
Out[30]: [0, 2, 4, 6, 8]

In [31]: l = l[1:-1] # this step is for slicing

In [32]: l
Out[32]: [2, 4, 6]
11
lmiguelvargasf

La plupart des réponses ci-dessus clarifient la notation Slice. La syntaxe d'indexation étendue utilisée pour le découpage est aList[start:stop:step] les exemples de base sont

enter image description here :

Autres exemples de découpage: 15 tranches étendues

11
Roshan Bagdiya

Le ci-dessous est l'exemple d'index d'une chaîne

 +---+---+---+---+---+
 | H | e | l | p | A |
 +---+---+---+---+---+
 0   1   2   3   4   5
-5  -4  -3  -2  -1

str="Name string"

exemple de découpage: [start: end: step]

str[start:end] # items start through end-1
str[start:]    # items start through the rest of the array
str[:end]      # items from the beginning through end-1
str[:]         # a copy of the whole array

Ci-dessous, l'exemple d'utilisation

print str[0]=N
print str[0:2]=Na
print str[0:7]=Name st
print str[0:7:2]=Nm t
print str[0:-1:2]=Nm ti
9
Prince Dhadwal

À mon avis, vous comprendrez et mémoriserez mieux la notation de découpage en chaîne Python si vous la regardez de la manière suivante (lisez la suite).

Travaillons avec la chaîne suivante ...

azString = "abcdefghijklmnopqrstuvwxyz"

Pour ceux qui ne le savent pas, vous pouvez créer n’importe quelle chaîne à partir de azString en utilisant la notation azString[x:y]

Venant d’autres langages de programmation, le sens commun est compromis. Que sont x et y?

Dans ma quête d'une technique de mémorisation, je devais m'asseoir et exécuter plusieurs scénarios qui me permettraient de me rappeler ce que x et y étaient et qui m'aideraient à trancher les chaînes correctement du premier coup.

Ma conclusion est que x et y doivent être considérés comme les index de limite entourant les chaînes que nous voulons extraire. Nous devrions donc voir l'expression sous la forme azString[index1, index2] ou plus clairement encore sous la forme azString[index_of_first_character, index_after_the_last_character].

Voici un exemple de visualisation de cette ...

Letters   a b c d e f g h i j ...
         ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 
Indexes  0 1 2 3 4 5 6 7 8 9 ... 
             |           |
cdefgh    index1       index2

Donc, tout ce que vous avez à faire si vous définissez index1 et index2 sur les valeurs qui entoureront la sous-chaîne souhaitée. Par exemple, pour obtenir la sous-chaîne "cdefgh", vous pouvez utiliser azString[2:8] car l'index situé à gauche de "c" est égal à 2 et celui à droite de "h", à 8.

Rappelez-vous que nous fixons les limites. Et ces limites sont les positions où vous pouvez placer des crochets qui seront enroulés autour de la sous-chaîne comme ceci ...

a b [ c d e f g h ] i j

Cette astuce fonctionne tout le temps et est facile à mémoriser.

8
asiby

Je souhaite ajouter un exemple Hello world expliquant les bases des tranches pour les tout-petits. Cela m'a beaucoup aidé.

Ayons une liste avec six valeurs ['P', 'Y', 'T', 'H', 'O', 'N']:

+---+---+---+---+---+---+
| P | Y | T | H | O | N |
+---+---+---+---+---+---+
  0   1   2   3   4   5 

Maintenant, les tranches les plus simples de cette liste sont ses sous-listes. La notation est [<index>:<index>] et la clé est de le lire comme ceci:

[ start cutting before this index : end cutting before this index ]

Maintenant, si vous faites une tranche [2:5] de la liste ci-dessus, cela se produira:

        |           |
+---+---|---+---+---|---+
| P | Y | T | H | O | N |
+---+---|---+---+---|---+
  0   1 | 2   3   4 | 5 

Vous avez effectué une coupe avant l'élément d'indice 2 et une autre coupe avant l'élément d'indice 5. Le résultat sera donc une tranche entre ces deux coupes, une liste ['T', 'H', 'O'].

7
Jeyekomon

Si vous pensez que les indices de découpage négatifs sont source de confusion, voici une manière très simple d’y réfléchir: il suffit de remplacer l’indice négatif par len - index. Ainsi, par exemple, remplacez -3 par len(list) - 3.

Le meilleur moyen d'illustrer ce que le découpage fait en interne consiste à l'indiquer dans le code qui implémente cette opération:

def slice(list, start = None, end = None, step = 1):
  # take care of missing start/end parameters
  start = 0 if start is None else start
  end = len(list) if end is None else end

  # take care of negative start/end parameters
  start = len(list) + start if start < 0 else start
  end = len(list) + end if end < 0 else end

  # now just execute for-loop with start, end and step
  return [list[i] for i in range(start, end, step)]
5
Shital Shah

Slice : - le serpent apparaît près de votre pied. Il passe de l'invisible au visible. Notre vision ne révèle (comme une tranche) qu'une partie du monde. de la même manière, une tranche Python extrait des éléments en fonction du début et de la fin. Nous prenons des tranches sur de nombreux types en Python. Nous spécifions un premier index facultatif, un dernier index facultatif et une étape facultative.

values[1:3]  Index 1 through index 3.
values[2:-1] Index 2 through index one from last.
values[:2]   Start through index 2.
values[2:]   Index 2 through end.
values[::2]  Start through end, skipping ahead 2 places each time.

vous pouvez obtenir de bons exemples en cliquant sur le lien ci-dessous: - exemple de notation python slice

4
SHASHI BHUSAN

La technique de base du découpage consiste à définir le point de départ, le point d'arrêt et la taille du pas, également appelés foulée.

Tout d'abord, nous allons créer une liste de valeurs à utiliser dans notre découpage.

Créez deux listes à découper, la première est une liste numérique de 1 à 9 (liste A). La seconde est aussi une liste numérique, comprise entre 0 et 9 (liste B)

A = list(range(1,10,1)) # start,stop,step
B = list(range(9))

print("This is List A:",A)
print("This is List B:",B)

Indexez le nombre 3 de A et le nombre 6 de B.

print(A[2])
print(B[6])

tranchage de base

La syntaxe d'indexation étendue utilisée pour le découpage est aList [start: stop: step]. L'argument start et l'argument step valent tous deux zéro. Le seul argument requis est stop. Avez-vous remarqué que cela ressemble à la façon dont la plage a été utilisée pour définir les listes A et B? En effet, l'objet slice représente l'ensemble des index spécifiés par range (start, stop, step). Python 3.4 documentation

Comme vous pouvez le constater, définir uniquement stop renvoie un élément. La valeur par défaut étant zéro pour le début, cela se traduit par la récupération d'un seul élément.

Il est important de noter que le premier élément est l'index 0, et non l'index 1. C'est pourquoi nous utilisons 2 listes pour cet exercice. Les éléments de la liste A sont numérotés en fonction de la position ordinale (le premier élément est 1, le deuxième élément est 2, etc.), tandis que les éléments de la liste B sont les numéros qui seraient utilisés pour les indexer ([0] pour le premier élément 0, etc. ).

Avec la syntaxe d'indexation étendue, nous récupérons une plage de valeurs. Par exemple, toutes les valeurs sont récupérées avec deux points.

A[:]

Pour récupérer un sous-ensemble d'éléments, les positions de départ et d'arrêt doivent être définies.

Étant donné le modèle aList [start: stop], récupérez les deux premiers éléments de la liste A

4
Babu Chandermani

Il est facile de comprendre si nous pourrions relier le découpage à range, ce qui donne les index. Nous pouvons catégoriser le découpage en tranches dans les deux catégories suivantes:


1. Aucune étape ou étape> 0. Par exemple, [i:j] ou [i:j:k] (k> 0)

Supposons que la séquence est s=[1,2,3,4,5].

  • si 0<i<len(s) et 0<j<len(s), alors [i:j:k] -> range(i,j,k)

Par exemple, [0:3:2] -> range(0,3,2) -> 0, 2

  • si i>len(s) ou j>len(s), alors i=len(s) ou j=len(s)

Par exemple, [0:100:2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4

  • si i<0 ou j<0, alors i=max(0,len(s)+i) ou j=max(0,len(s)+j)

Par exemple, [0:-3:2] -> range(0,len(s)-3,2) -> range(0,2,2) -> 0

Pour un autre exemple, [0:-1:2] -> range(0,len(s)-1,2) -> range(0,4,2) -> 0, 2

  • si i n'est pas spécifié, alors i=0

Par exemple, [:4:2] -> range(0,4,2) -> range(0,4,2) -> 0, 2

  • si j n'est pas spécifié, alors j=len(s)

Par exemple, [0::2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4


2. Étape <0. Par exemple, [i:j:k] (k <0)

Supposons que la séquence est s=[1,2,3,4,5].

  • si 0<i<len(s) et 0<j<len(s), alors [i:j:k] -> range(i,j,k)

Par exemple, [5:0:-2] -> range(5,0,-2) -> 5, 3, 1

  • si i>len(s) ou j>len(s), alors i=len(s)-1 ou j=len(s)-1

Par exemple, [100:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

  • si i<0 ou j<0, alors i=max(-1,len(s)+i) ou j=max(-1,len(s)+j)

Par exemple, [-2:-10:-2] -> range(len(s)-2,-1,-2) -> range(3,-1,-2) -> 3, 1

  • si i n'est pas spécifié, alors i=len(s)-1

Par exemple, [:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

  • si j n'est pas spécifié, alors j=-1

Par exemple, [2::-2] -> range(2,-1,-2) -> 2, 0

Pour un autre exemple, [::-1] -> range(len(s)-1,-1,-1) -> range(4,-1,-1) -> 4, 3, 2, 1, 0


En résumé

enter image description here

2
Banghua Zhao

Je ne pense pas que le diagramme tutoriel Python (cité dans diverses autres réponses) soit bon, car cette suggestion fonctionne pour une foulée positive, mais pas pour une foulée négative.

Voici le diagramme:

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1

D'après le diagramme, j'attends que a[-4,-6,-1] soit yP mais c'est ty.

>>> a = "Python"
>>> a[2:4:1] # as expected
'th'
>>> a[-4:-6:-1] # off by 1
'ty'

Ce qui marche toujours, c’est de penser en caractères ou en cases et d’utiliser l’indexation comme un intervalle semi-ouvert - ouverture à droite si la foulée est positive, à gauche si la foulée est négative.

De cette façon, je peux penser à a[-4:-6:-1] comme a(-6,-4] dans la terminologie d'intervalle.

 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5  
  -6  -5  -4  -3  -2  -1

 +---+---+---+---+---+---+---+---+---+---+---+---+
 | P | y | t | h | o | n | P | y | t | h | o | n |
 +---+---+---+---+---+---+---+---+---+---+---+---+
  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5  
1
aguadopd

Je suis un peu frustré de ne pas trouver une source en ligne ou une documentation Python décrivant précisément le découpage.

J'ai suivi la suggestion d'Aaron Hall et lu les parties pertinentes du code source de CPython, puis j'ai écrit du code Python qui effectue le découpage de la même manière que dans CPython. J'ai testé mon code dans Python 3 sur des millions de tests aléatoires sur des listes d'entiers.

Vous trouverez peut-être utile dans mon code les références aux fonctions correspondantes dans CPython.

# return the result of slicing list x
# See the part of list_subscript() in listobject.c that pertains
# to when the indexing item is a PySliceObject
def slicer(x, start=None, stop=None, step=None):
    # Handle slicing index values of None, and a step value of 0.
    # See PySlice_Unpack() in sliceobject.c, which
    # extracts start, stop, step from a PySliceObject.
    maxint = 10000000       # a hack to simulate PY_SSIZE_T_MAX
    if step == None:
        step = 1
    Elif step == 0:
        raise ValueError('slice step cannot be zero')

    if start == None:
        start = maxint if step < 0 else 0
    if stop == None:
        stop = -maxint if step < 0 else maxint

    # Handle negative slice indexes and bad slice indexes.
    # Compute number of elements in the slice as slice_length.
    # See PySlice_AdjustIndices() in sliceobject.c
    length = len(x)
    slice_length = 0

    if start < 0:
        start += length
        if start < 0:
            start = -1 if step < 0 else 0
    Elif start >= length:
        start = length - 1 if step < 0 else length

    if stop < 0:
        stop += length
        if stop < 0:
            stop = -1 if step < 0 else 0
    Elif stop > length:
        stop = length - 1 if step < 0 else length

    if step < 0:
        if stop < start:
            slice_length = (start - stop - 1) // (-step) + 1
    else: 
        if start < stop:
            slice_length = (stop - start - 1) // step + 1

    # cases of step = 1 and step != 1 are treated separately
    if slice_length <= 0:
        return []
    Elif step == 1:
        # see list_slice() in listobject.c
        result = []
        for i in range(stop - start):
            result.append(x[i+start])
        return result
    else:
        result = []
        cur = start
        for i in range(slice_length):
            result.append(x[cur])
            cur += step
        return result
1
grbruns

Personnellement, j'y pense comme une boucle

a[start:end:step]    
# for(i = start; i < end; i += step)

Notez également que les valeurs négatives pour start et end sont relatives à la fin de la liste.

0
Raman