Qu'est-ce que :: (double colon) en Python lors de la souscription de séquences?


264

Je sais que je peux utiliser quelque chose comme string[3:4]pour obtenir une sous-chaîne en Python, mais que signifie le 3 somesequence[::3]?


qu'est-ce que cela signifie qui vient avant :: comme [5::]. Alors qu'est-ce que cela signifie par 5?
Umar Asghar

1
[5 ::] signifierait commencer par le premier élément, rien pour le second et sélectionner l'élément suivant
Gagan

Réponses:


243

cela signifie «rien pour le premier argument, rien pour le second et sautez par trois». Il obtient chaque troisième élément de la séquence en tranches. Les tranches étendues sont ce que vous voulez. Nouveau dans Python 2.3


99
Il peut également être utilisé pour inverser une liste en utilisant [:: - 1]
thavan

22
Il renvoie chaque élément sur une position qui est un multiple de 3 . Puisque 3 * 0 = 0, il renvoie également l'élément sur la position 0. Par exemple: range(10)[::3]sorties[0, 3, 6, 9]
Ricky Robinson

1
qu'est-ce que cela signifie qui vient avant ::comme [n ::]. Alors qu'est-ce que cela signifie n?
Umar Asghar

154

Les adresses de tranche de séquence Python peuvent être écrites sous la forme [début: fin: étape] et tout début, fin ou fin peut être supprimé. a[::3]est chaque troisième élément de la séquence.


85

seq[::n]est une séquence de chaque nélément sur la séquence entière.

Exemple:

>>> range(10)[::2]
[0, 2, 4, 6, 8]

La syntaxe est:

seq[start:end:step]

Vous pouvez donc faire:

>>> range(100)[5:18:2]
[5, 7, 9, 11, 13, 15, 17]

4
Dans Python 3, votre exemple de plage (N) [:: step] produit un objet plage, pas une liste. Pour vraiment voir ce qui se passe, vous devez contraindre la plage à une liste, np.array, etc.
PikalaxALT

57

Explication

s[i:j:k]est, selon la documentation , "tranche de s de i à j à l'étape k". Lorsque iet jsont absents, toute la séquence est supposée et doncs[::k] signifie "chaque k-ème élément".

Exemples

Tout d'abord, initialisons une liste:

>>> s = range(20)
>>> s
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Prenons tous les 3 e point de s:

>>> s[::3]
[0, 3, 6, 9, 12, 15, 18]

Prenons tous les 3 e point de s[2:]:

>>> s[2:]
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> s[2::3]
[2, 5, 8, 11, 14, 17]

Prenons tous les 3 e point de s[5:12]:

>>> s[5:12]
[5, 6, 7, 8, 9, 10, 11]
>>> s[5:12:3]
[5, 8, 11]

Prenons tous les 3 e point de s[:10]:

>>> s[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> s[:10:3]
[0, 3, 6, 9]

réponse incroyable!
Jürgen K.

30

TL; DR

Cet exemple visuel vous montrera comment sélectionner soigneusement des éléments dans une matrice NumPy (tableau à 2 dimensions) d'une manière assez divertissante (je vous le promets). L'étape 2 ci-dessous illustre l'utilisation de ce «double-deux-points» ::en question.

(Attention: il s'agit d'un exemple spécifique au tableau NumPy dans le but d'illustrer le cas d'utilisation des "deux-points" ::pour sauter des éléments sur plusieurs axes. Cet exemple ne couvre pas les structures de données Python natives comme List).

Un exemple concret pour les gouverner tous ...

Disons que nous avons une matrice NumPy qui ressemble à ceci:

In [1]: import numpy as np

In [2]: X = np.arange(100).reshape(10,10)

In [3]: X
Out[3]:
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
       [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])

Dites pour une raison quelconque, votre patron veut que vous sélectionniez les éléments suivants:

entrez la description de l'image ici

"Mais comment ???" ... Continuez à lire! (Nous pouvons le faire dans une approche en 2 étapes)

Étape 1 - Obtenir un sous-ensemble

Spécifiez l '"index de début" et l' "index de fin" dans les deux directions, ligne par ligne et colonne.

entrez la description de l'image ici

Dans du code:

In [5]: X2 = X[2:9,3:8]

In [6]: X2
Out[6]:
array([[23, 24, 25, 26, 27],
       [33, 34, 35, 36, 37],
       [43, 44, 45, 46, 47],
       [53, 54, 55, 56, 57],
       [63, 64, 65, 66, 67],
       [73, 74, 75, 76, 77],
       [83, 84, 85, 86, 87]])

Notez maintenant que nous venons d'obtenir notre sous-ensemble, avec l'utilisation d'une technique d'indexation simple de début et de fin. Ensuite, comment faire ce "saut" ... (lire la suite!)

Étape 2 - Sélectionnez les éléments (avec l'argument "étape de saut")

Nous pouvons maintenant spécifier les «étapes de saut» dans les deux directions, ligne par ligne et colonne (pour sélectionner les éléments de manière «sautante») comme ceci:

entrez la description de l'image ici

Dans le code (notez les deux-points):

In [7]: X3 = X2[::3, ::2]

In [8]: X3
Out[8]:
array([[23, 25, 27],
       [53, 55, 57],
       [83, 85, 87]])

Nous venons de sélectionner tous les éléments selon vos besoins! :)

 Consolidez l'étape 1 (début et fin) et l'étape 2 ("saut")

Maintenant que nous connaissons le concept, nous pouvons facilement combiner les étapes 1 et 2 en une seule étape consolidée - pour plus de compacité:

In [9]: X4 = X[2:9,3:8][::3,::2]

    In [10]: X4
    Out[10]:
    array([[23, 25, 27],
           [53, 55, 57],
           [83, 85, 87]])

Terminé!


Que faire si je veux définir chacune de ces entrées marquées à 0 dans l'objet d'origine? La façon de procéder?
user1211030

1
Faites un X[2:9,3:8][::3,::2] = 0 (pour remplacer les entrées marquées par 0). Si vous tapez à Xnouveau, vous verrez que toutes ces entrées marquées sont maintenant définies sur 0.
Atlas7

15

Lors du découpage en Python, le troisième paramètre est l'étape. Comme d'autres l'ont mentionné, voir Extended Slices pour un bon aperçu.

Avec cette connaissance, [::3]cela signifie simplement que vous n'avez spécifié aucun indice de début ou de fin pour votre tranche. Puisque vous avez spécifié une étape, 3cela prendra toutes les trois entrées de somethingdépart au premier index. Par exemple:

>>> '123123123'[::3]
'111'

7

Vous pouvez également utiliser cette notation dans vos propres classes personnalisées pour faire ce que vous voulez

class C(object):
    def __getitem__(self, k):
        return k

# Single argument is passed directly.
assert C()[0] == 0

# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)

# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)

# If you omit any part of the slice notation, it becomes None.
assert C()[:] == slice(None, None, None)
assert C()[::] == slice(None, None, None)
assert C()[1::] == slice(1, None, None)
assert C()[:2:] == slice(None, 2, None)
assert C()[::3] == slice(None, None, 3)

# Tuple with a slice object:
assert C()[:, 1] == (slice(None, None, None), 1)

# Ellipsis class object.
assert C()[...] == Ellipsis

Nous pouvons ensuite ouvrir les objets tranche comme:

s = slice(1, 2, 3)
assert s.start == 1
assert s.stop == 2
assert s.step == 3

Ceci est notamment utilisé dans Numpy pour découper des tableaux multidimensionnels dans n'importe quelle direction.

Bien sûr, toute API sensée doit utiliser ::3la sémantique habituelle "tous les 3".

Le sujet Ellipsisest traité plus loin à: Que fait l'objet Ellipsis?


6

Le troisième paramètre est l'étape. Donc [:: 3] retournerait chaque 3e élément de la liste / chaîne.


4

Python utilise le :: pour séparer la valeur End, Start et Step.


1
Cela ne fournit pas suffisamment de détails pour être réellement utile.
bstpierre

4
Vous ne voulez pas dire "le début, la fin et l'étape"? Semble trompeur de les énumérer hors service.
Jon Coombs
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.