Was ist :: (Doppelpunkt) in Python beim Abonnieren von Sequenzen?

262

Ich weiß, dass ich so etwas wie string[3:4]einen Teilstring in Python verwenden kann, aber was bedeutet die 3 in somesequence[::3]?

Aillyn
quelle
Was bedeutet es, der kommt vor :: wie [5::]. Was bedeutet es also mit 5?
Umar Asghar
1
[5 ::] würde bedeuten, mit dem ersten Element zu beginnen, nichts für das zweite und das nächste Element auszuwählen
Gagan

Antworten:

241

es bedeutet "nichts für das erste Argument, nichts für das zweite und springe um drei". Es wird jedes dritte Element der Sequenz in Scheiben geschnitten. Erweiterte Scheiben ist das, was Sie wollen. Neu in Python 2.3

Adriano Varoli Piazza
quelle
98
Es kann auch verwendet werden, um eine Liste mit [:: - 1]
thavan
22
Es gibt jedes Element an einer Position zurück, die ein Vielfaches von 3 ist . Da 3 * 0 = 0 ist, wird auch das Element auf Position 0 zurückgegeben. Zum Beispiel: range(10)[::3]Ausgaben[0, 3, 6, 9]
Ricky Robinson
1
Was bedeutet es, wer ::wie [n ::] vorher kommt ? Was bedeutet es also n?
Umar Asghar
153

Python-Sequenz-Slice-Adressen können als [Start: Ende: Schritt] geschrieben werden, und Start, Stopp oder Ende können gelöscht werden. a[::3]ist jedes dritte Element der Sequenz.

deinst
quelle
84

seq[::n]ist eine Folge jedes n-ten Elements in der gesamten Folge.

Beispiel:

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

Die Syntax lautet:

seq[start:end:step]

So können Sie tun:

>>> range(100)[5:18:2]
[5, 7, 9, 11, 13, 15, 17]
Yuval Adam
quelle
4
In Python 3 erzeugt Ihr Beispielbereich (N) [:: Schritt] ein Bereichsobjekt, keine Liste. Um wirklich zu sehen, was passiert, müssen Sie den Bereich auf eine Liste, np.array usw.
zwingen
57

Erläuterung

s[i:j:k]ist laut Dokumentation "Scheibe von s von i nach j mit Schritt k". Wenn iund jfehlen, wird die gesamte Sequenz angenommen und s[::k]bedeutet somit "jedes k-te Element".

Beispiele

Lassen Sie uns zunächst eine Liste initialisieren:

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

Nehmen wir jeden dritten Gegenstand aus s:

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

Nehmen wir jeden dritten Gegenstand aus 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]

Nehmen wir jeden dritten Gegenstand aus s[5:12]:

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

Nehmen wir jeden dritten Gegenstand aus s[:10]:

>>> s[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> s[:10:3]
[0, 3, 6, 9]
Bolo
quelle
erstaunliche Antwort!
Jürgen K.
29

TL; DR

Dieses visuelle Beispiel zeigt Ihnen, wie Sie Elemente in einer NumPy-Matrix (zweidimensionales Array) auf unterhaltsame Weise ordentlich auswählen (ich verspreche es). Schritt 2 unten veranschaulicht die Verwendung dieses ::fraglichen "Doppelpunkts" .

(Achtung: Dies ist ein NumPy-Array-spezifisches Beispiel mit dem Ziel, den Anwendungsfall von "Doppelpunkt" ::für das Springen von Elementen in mehreren Achsen zu veranschaulichen . Dieses Beispiel behandelt keine nativen Python-Datenstrukturen wie List).

Ein konkretes Beispiel, um sie alle zu regieren ...

Angenommen, wir haben eine NumPy-Matrix, die folgendermaßen aussieht:

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

Sagen Sie aus irgendeinem Grund, Ihr Chef möchte, dass Sie die folgenden Elemente auswählen:

Geben Sie hier die Bildbeschreibung ein

"Aber wie ???" ... Lesen Sie weiter! (Wir können dies in einem 2-Schritt-Ansatz tun)

Schritt 1 - Erhalten Sie eine Teilmenge

Geben Sie den "Startindex" und den "Endindex" in zeilen- und spaltenweiser Richtung an.

Geben Sie hier die Bildbeschreibung ein

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

Beachten Sie, dass wir gerade unsere Teilmenge mithilfe der einfachen Start- und Endindizierungstechnik erhalten haben. Als nächstes, wie man das "Springen" macht ... (lesen Sie weiter!)

Schritt 2 - Elemente auswählen (mit dem Argument "Sprungschritt")

Wir können nun die "Sprungschritte" sowohl in zeilen- als auch in spaltenweiser Richtung angeben (um Elemente auf "springende" Weise auszuwählen):

Geben Sie hier die Bildbeschreibung ein

Im Code (beachten Sie die Doppelpunkte):

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

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

Wir haben gerade alle Elemente nach Bedarf ausgewählt! :) :)

 Konsolidieren Sie Schritt 1 (Start und Ende) und Schritt 2 ("Springen")

Jetzt, da wir das Konzept kennen, können wir Schritt 1 und Schritt 2 einfach zu einem konsolidierten Schritt kombinieren - für Kompaktheit:

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

Getan!

Atlas7
quelle
Was ist, wenn ich jeden dieser markierten Einträge im Originalobjekt auf 0 setzen möchte? Wie gehe ich vor?
user1211030
1
Führen Sie a aus X[2:9,3:8][::3,::2] = 0 (um die markierten Einträge durch 0 zu ersetzen). Wenn Sie Xerneut eingeben, werden alle markierten Einträge auf gesetzt 0.
Atlas7
15

Beim Schneiden in Python ist der dritte Parameter der Schritt. Wie bereits erwähnt, finden Sie unter Erweiterte Slices eine schöne Übersicht.

Mit diesem Wissen [::3]bedeutet dies nur, dass Sie keine Start- oder Endindizes für Ihr Slice angegeben haben. Da Sie einen Schritt angegeben haben 3, wird bei jedem dritten Eintrag somethingmit dem ersten Index begonnen. Zum Beispiel:

>>> '123123123'[::3]
'111'
Justin Ethier
quelle
7

Sie können diese Notation auch in Ihren eigenen benutzerdefinierten Klassen verwenden, damit sie das tut, was Sie wollen

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

Wir können dann Slice-Objekte öffnen als:

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

Dies wird insbesondere in Numpy verwendet, um mehrdimensionale Arrays in jede Richtung zu schneiden.

Natürlich sollte jede vernünftige API ::3mit der üblichen "alle 3" -Semantik verwendet werden.

Das Verwandte Ellipsiswird weiter behandelt unter: Was macht das Ellipsis-Objekt?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
6

Der dritte Parameter ist der Schritt. Also würde [:: 3] jedes dritte Element der Liste / Zeichenfolge zurückgeben.

mshafrir
quelle
4

Python verwendet das ::, um den End-, den Start- und den Step-Wert zu trennen.

POWERRANGERDUDEONCAPS
quelle
1
Dies liefert nicht genügend Details, um tatsächlich hilfreich zu sein.
Bstpierre
4
Meinst du nicht "der Anfang, das Ende und der Schritt"? Scheint irreführend, sie nicht in der richtigen Reihenfolge aufzulisten.
Jon Coombs