Frage

Ich brauche eine gute Erklärung (Referenzen sind ein Plus) zur Slice-Notation von Python.

Für mich muss diese Notation ein wenig erlernt werden.

Es sieht extrem kraftvoll aus, aber ich habe es noch nicht ganz verstanden.

War es hilfreich?

Lösung

Es ist wirklich ziemlich einfach:

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

Es gibt auch die step Wert, der mit einem der oben genannten verwendet werden kann:

a[start:stop:step] # start through not past stop, by step

Der entscheidende Punkt, an den man sich erinnert, ist, dass die :stop Wert repräsentiert den ersten Wert, der ist nicht in der ausgewählten Scheibe. Also der Unterschied zwischen stop und start ist die Anzahl der ausgewählten Elemente (wenn step ist 1, der Standard).

Das andere Merkmal ist das start oder stop vielleicht ein Negativ Nummer, was bedeutet, dass es vom Ende des Arrays statt am Anfang zählt. So:

a[-1]    # last item in the array
a[-2:]   # last two items in the array
a[:-2]   # everything except the last two items

Ähnlich, step kann eine negative Zahl sein:

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 ist freundlich zum Programmierer, wenn es weniger Artikel gibt, als Sie verlangen. Zum Beispiel, wenn Sie danach fragen a[:-2] und a Enthält nur ein Element, Sie erhalten eine leere Liste anstelle eines Fehlers. Manchmal bevorzugen Sie den Fehler, daher müssen Sie sich bewusst sein, dass dies möglicherweise passieren kann.

Beziehung zu slice() Objekt

Der Schnittbetreiber [] wird tatsächlich im obigen Code mit a verwendet slice() Objekt mit dem : Notation (die nur innerhalb gültig ist []), dh:

a[start:stop:step]

ist äquivalent zu:

a[slice(start, stop, step)]

Slice -Objekte verhalten sich je nach Anzahl der Argumente auch etwas unterschiedlich, ähnlich wie range(), dh beides slice(stop) und slice(start, stop[, step]) sind unterstützt. Um ein bestimmtes Argument anzugeben, könnte man verwenden None, so dass z. a[start:] ist äquivalent zu a[slice(start, None)] oder a[::-1] ist äquivalent zu a[slice(None, None, -1)].

Während :-Basierte Notation ist sehr hilfreich für einfaches Schneiden, die explizite Verwendung von slice() Objekte vereinfachen die programmatische Erzeugung des Schneidens.

Andere Tipps

Das Python Tutorial Gespräche darüber (scrollen Sie ein wenig nach unten, bis Sie zu dem Teil zum Schneiden kommen).

Das ASCII -Kunstdiagramm ist auch hilfreich, um sich daran zu erinnern, wie Scheiben funktionieren:

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

Eine Möglichkeit, sich daran zu erinnern, wie Scheiben funktionieren zwischen Zeichen, mit der linken Kante des ersten Zeichens Nummer 0. Dann die rechte Kante des letzten Zeichens einer Zeichenfolge von n Zeichen hat Index n.

Aufzählung der von der Grammatik zulässigen Möglichkeiten:

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

Natürlich, wenn (high-low)%stride != 0, dann ist der Endpunkt etwas niedriger als high-1.

Wenn stride ist negativ, die Bestellung wird ein wenig geändert, da wir zählen:

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

Erweitertes Schneiden (mit Kommas und Ellipsen) werden hauptsächlich nur von speziellen Datenstrukturen (wie Numpy) verwendet. Die grundlegenden Sequenzen unterstützen sie nicht.

>>> class slicee:
...     def __getitem__(self, item):
...         return repr(item)
...
>>> slicee()[0, 1:2, ::5, ...]
'(0, slice(1, 2, None), slice(None, None, 5), Ellipsis)'

Die obigen Antworten diskutieren nicht die Slice -Zuordnung. Um die Slice -Aufgabe zu verstehen, ist es hilfreich, der ASCII -Kunst ein weiteres Konzept hinzuzufügen:

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

Eine Heuristik ist für eine Scheibe von Null nach N: "Null ist der Anfang, beginne am Anfang und nimm n Elemente in eine 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']

Eine andere Heuristik ist: "Für jede Scheibe den Start durch Null ersetzen, die vorherige Heuristik anwenden, um das Ende der Liste zu erreichen, und dann die erste Nummer wieder aufzunehmen, um Gegenstände vom Anfang abzuschneiden."

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

Die erste Regel der Slice -Zuordnung ist, dass seit schnitten kehrt zurück eine Liste, Scheibenzuweisung erfordert eine Liste (oder andere iterable):

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

Die zweite Regel der Slice -Zuordnung, die Sie oben auch sehen können, ist, dass jeder Teil der Liste durch die Slice -Indexierung zurückgegeben wird. Dies ist der gleiche Teil, der durch Slice -Zuordnung geändert wird:

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

Die dritte Regel der Slice -Zuordnung ist, dass die zugewiesene Liste (iterable) nicht die gleiche Länge haben muss. Die indizierte Scheibe wird einfach ausgeschaltet und in Massen durch alles ersetzt, was zugewiesen wird:

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

Der schwierigste Teil, an das Sie sich gewöhnen können, ist die Aufgabe zu leeren Scheiben. Mit Heuristic 1 und 2 ist es einfach, Ihren Kopf herumzukommen Indizierung eine leere Scheibe:

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

Und dann, sobald Sie das gesehen haben, ist auch die Zuordnung zum leeren Schicht sinnvoll:

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

Beachten Sie, dass die eingefügten Elemente, da wir nicht die zweite Anzahl der Slice (4) ändern, immer direkt gegen das 'o' stapeln, selbst wenn wir dem leeren Scheiben zuweisen. Die Position für die leere Slice-Zuordnung ist also die logische Erweiterung der Positionen für die nicht leeren Scheibenzuordnungen.

Was passiert ein bisschen, wenn Sie mit unserer Prozession weitermachen, um den Slice -Beginn zu zählen?

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

Wenn Sie fertig sind, sind Sie fertig, wenn Sie fertig sind. Es fängt nicht nach hinten an. In Python erhalten Sie keine negativen Fortschritte, es sei denn, Sie fragen sie ausdrücklich darum, indem Sie eine negative Zahl verwenden.

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

Es gibt einige seltsame Konsequenzen für die Regel "Sobald Sie fertig sind, Sie sind fertig":

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

In der Tat ist im Vergleich zur Indexierung das Python-Slicing bizarr fehlerhaft:

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

Dies kann manchmal nützlich sein, aber es kann auch zu etwas seltsamem Verhalten führen:

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

Abhängig von Ihrer Bewerbung könnte das ... oder auch nicht ... Seien Sie das, worauf Sie sich dort gehofft haben!


Unten ist der Text meiner ursprünglichen Antwort. Es war für viele Menschen nützlich, also wollte ich es nicht löschen.

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

Dies kann auch den Unterschied zwischen Schneiden und Indexierung verdeutlichen.

Erklären Sie die Slice-Notation von Python

Kurz gesagt, die Doppelpunkte (:) in tiefgestellter Notation (subscriptable[subscriptarg]) Slice-Notation erstellen – mit den optionalen Argumenten, start, stop, step:

sliceable[start:stop:step]

Python-Slicing ist eine rechenschnelle Möglichkeit, methodisch auf Teile Ihrer Daten zuzugreifen.Meiner Meinung nach ist es, um auch nur ein fortgeschrittener Python-Programmierer zu sein, ein Aspekt der Sprache, mit dem man vertraut sein muss.

Wichtige Definitionen

Lassen Sie uns zunächst einige Begriffe definieren:

Start: der Anfangsindex des Slice, es wird das Element an diesem Index einschließen, es sei denn, es ist dasselbe wie stoppen, ist standardmäßig 0, d. h.der erste Index.Wenn es negativ ist, bedeutet es, anzufangen n Artikel vom Ende.

stoppen: Der Endindex des Slice ist der Fall nicht Fügen Sie das Element an diesem Index ein. Standardmäßig wird die Länge der in Scheiben geschnittenen Sequenz verwendet, d. h. bis einschließlich zum Ende.

Schritt: Der Betrag, um den der Index steigt, ist standardmäßig 1.Wenn es negativ ist, überschneiden Sie das Iterable in umgekehrter Reihenfolge.

So funktioniert die Indizierung

Sie können jede dieser positiven oder negativen Zahlen eingeben.Die Bedeutung der positiven Zahlen ist einfach, aber bei negativen Zahlen zählt man, genau wie bei Indizes in Python, vom Ende an rückwärts Start Und stoppen, und für die Schritt, dekrementieren Sie einfach Ihren Index.Dieses Beispiel ist aus dem Tutorial der Dokumentation, aber ich habe es leicht geändert, um anzugeben, auf welches Element in einer Sequenz jeder Index verweist:

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

So funktioniert das Schneiden

Um die Slice-Notation mit einer Sequenz zu verwenden, die sie unterstützt, müssen Sie mindestens einen Doppelpunkt in die eckigen Klammern einfügen, die auf die Sequenz folgen (was eigentlich der Fall ist). das umsetzen __getitem__ Methode der Sequenz gemäß dem Python-Datenmodell.)

Die Slice-Notation funktioniert folgendermaßen:

sequence[start:stop:step]

Und denken Sie daran, dass es Standardeinstellungen für gibt Start, stoppen, Und Schritt, um also auf die Standardeinstellungen zuzugreifen, lassen Sie einfach das Argument weg.

Die Slice-Notation zum Abrufen der letzten neun Elemente aus einer Liste (oder einer anderen Sequenz, die sie unterstützt, z. B. einem String) würde wie folgt aussehen:

my_list[-9:]

Wenn ich das sehe, las ich den Teil in den Klammern als "9. vom Ende, bis zum Ende". (Eigentlich habe ich es mental als "-9, on" abkürze)

Erläuterung:

Die vollständige Notation ist

my_list[-9:None:None]

und die Standardwerte zu ersetzen (eigentlich wann step ist negativ, stopDie Standardeinstellung ist -len(my_list) - 1, Also None denn Stopp bedeutet eigentlich nur, dass es zu dem Endschritt geht, zu dem es führt):

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

Der Doppelpunkt, :, teilt Python mit, dass Sie ihm ein Slice und keinen regulären Index geben.Aus diesem Grund lautet die idiomatische Methode zum Erstellen einer flachen Kopie von Listen in Python 2

list_copy = sequence[:]

Und das Löschen erfolgt mit:

del my_list[:]

(Python 3 erhält eine list.copy Und list.clear Methode.)

Wann step ist negativ, die Standardwerte für start Und stop ändern

Standardmäßig, wenn die step Argument ist leer (oder None), es ist zugeordnet +1.

Sie können jedoch eine negative Ganzzahl übergeben, und die Liste (oder die meisten anderen Standard-Slicables) wird vom Ende zum Anfang aufgeteilt.

Somit ändert ein negativer Slice die Standardeinstellungen für start Und stop!

Bestätige dies in der Quelle

Ich ermutige Benutzer gerne, sowohl die Quelle als auch die Dokumentation zu lesen.Der Quellcode für Slice-Objekte und diese Logik finden Sie hier.Zuerst stellen wir fest, ob step ist negativ:

 step_is_negative = step_sign < 0;

Wenn ja, ist die Untergrenze -1 Das heißt, wir schneiden den gesamten Weg bis zum Anfang und einschließlich, und die Obergrenze ist die Länge minus 1, was bedeutet, dass wir am Ende beginnen.(Beachten Sie, dass die Semantik davon -1 Ist anders von einem -1 dass Benutzer Indizes in Python übergeben können, die das letzte Element angeben.)

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

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

Ansonsten step ist positiv, und die untere Grenze ist Null und die obere Grenze (die wir erreichen, aber nicht einbeziehen) die Länge der segmentierten Liste.

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

Dann müssen wir möglicherweise die Standardeinstellungen anwenden start Und stop - der Standard dann für start wird als Obergrenze berechnet, wenn step ist negativ:

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

Und stop, die untere Grenze:

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

Geben Sie Ihren Slices einen aussagekräftigen Namen!

Möglicherweise ist es sinnvoll, das Bilden des Schnitts von der Weitergabe an den Schnitt zu trennen list.__getitem__ Methode (Das ist es, was die eckigen Klammern bewirken).Selbst wenn Sie kein Neuling darin sind, bleibt Ihr Code dadurch besser lesbar, sodass andere, die Ihren Code möglicherweise lesen müssen, leichter verstehen können, was Sie tun.

Sie können einer Variablen jedoch nicht einfach einige durch Doppelpunkte getrennte Ganzzahlen zuweisen.Sie müssen das Slice-Objekt verwenden:

last_nine_slice = slice(-9, None)

Das zweite Argument, None, ist erforderlich, damit das erste Argument als interpretiert wird start Streit sonst wäre es das stop Streit.

Anschließend können Sie das Slice-Objekt an Ihre Sequenz übergeben:

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

Es ist interessant, dass Bereiche auch Slices benötigen:

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

Überlegungen zum Speicher:

Da Slices von Python-Listen neue Objekte im Speicher erstellen, ist eine weitere wichtige Funktion zu beachten itertools.islice.Normalerweise möchten Sie ein Slice durchlaufen und es nicht nur statisch im Speicher erstellen lassen. islice ist dafür perfekt.Eine Einschränkung: Negative Argumente werden nicht unterstützt start, stop, oder step, Wenn dies also ein Problem darstellt, müssen Sie möglicherweise Indizes berechnen oder die Iteration im Voraus umkehren.

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

und nun:

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

Die Tatsache, dass Listenabschnitte eine Kopie erstellen, ist ein Merkmal der Listen selbst.Wenn Sie erweiterte Objekte wie einen Pandas DataFrame aufteilen, wird möglicherweise eine Ansicht des Originals und keine Kopie zurückgegeben.

Und ein paar Dinge, die mir nicht sofort offensichtlich waren, als ich die Slicing -Syntax zum ersten Mal sah:

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

Einfache Möglichkeit, Sequenzen umzukehren!

Und wenn Sie wollten, jeder zweite Element in der umgekehrten Sequenz:

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

In Python 2.7

In Python schneiden

[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).

Das Verständnis der Indexzuordnung ist sehr wichtig.

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

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

Wenn Sie [A: B: C] sagen, sagen Sie je nach Zeichen von C (vorwärts oder rückwärts), beginnen Sie bei A und enden Sie bei B (ohne Element bei BTH Index). Verwenden Sie die oben genannte Indexierungsregel und denken Sie daran, dass Sie nur Elemente in diesem Bereich finden:

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

Aber dieser Bereich setzt sich unendlich in beide Richtungen fort:

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

Zum Beispiel:

             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

Wenn Ihre Wahl von A, B und C überlappen, dass Sie sich mit dem obigen Bereich überlappen, wenn Sie Regeln für A, B, C oben durchqueren, erhalten Sie entweder eine Liste mit Elementen (berührt während der Durchquerung) oder Sie erhalten eine leere Liste.

Eine letzte Sache: Wenn A und B gleich sind, erhalten Sie auch eine leere Liste:

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

Fand diesen tollen Tisch bei 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)

Nachdem ich es ein bisschen verwendet habe, stelle ich fest, dass die einfachste Beschreibung darin besteht, dass es genau das gleiche ist wie die Argumente in a for Schleife...

(from:to:step)

Jeder von ihnen ist optional:

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

Anschließend muss die negative Indexierung nur die Länge der Zeichenfolge zu den negativen Indizes hinzufügen, um sie zu verstehen.

Das funktioniert sowieso für mich ...

Ich finde es einfacher, mich daran zu erinnern, wie es funktioniert, und dann kann ich eine bestimmte Kombination aus Start/Stopp/Schritt herausfinden.

Es ist lehrreich zu verstehen range() Erste:

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

Beginnen Sie von start, inkrementiert durch step, nicht erreichen stop. Sehr einfach.

Die Sache, an die man sich an einen negativen Schritt erinnern muss, ist das stop ist immer das ausgeschlossene Ende, egal ob es höher oder niedriger ist. Wenn Sie die gleiche Scheibe in entgegengesetzter Reihenfolge möchten, ist es viel sauberer, die Umkehrung separat durchzuführen: z. 'abcde'[1:-2][::-1] Scheiben Sie einen Zeichen von links ab, zwei von rechts und kehrt dann um. (Siehe auch reversed().)

Die Sequenzschneide ist gleich, außer dass es zuerst negative Indizes normalisiert und niemals außerhalb der Sequenz gehen kann:

MACHEN: Der folgende Code hatte einen Fehler mit "niemals außerhalb der Sequenz gehen", wenn ABS (Schritt)> 1; ich denken Ich habe es gepatcht, um korrekt zu sein, aber es ist schwer zu verstehen.

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]

Mach dir keine Sorgen um die is None Details - denken Sie nur daran, dass weglassen start und/oder stop tut immer das Richtige, um Ihnen die ganze Sequenz zu geben.

Durch die Normalisierung negativer Indizes zuerst können Start und/oder Stopp unabhängig vom Ende gezählt werden: 'abcde'[1:-2] == 'abcde'[1:3] == 'bc' Trotz range(1,-2) == []. Die Normalisierung wird manchmal als "Modulo der Länge" angesehen, aber beachten Sie, dass sie die Länge nur einmal hinzufügt: z. 'abcde'[-53:42] ist nur die ganze Saite.

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

Ich hoffe, dies hilft Ihnen, die Liste in Python zu modellieren.

Bezug: http://wiki.python.org/moin/movingtopythonfromotherlanguages

Ich verwende die Methode "ein Indexpunkt zwischen Elementen", um selbst darüber nachzudenken, aber eine Möglichkeit, sie zu beschreiben, die manchmal anderen hilft, es zu bekommen, ist Folgendes:

mylist[X:Y]

X ist der Index des ersten Elements, das Sie wollen.
Y ist der Index des ersten Elements, das Sie nicht wollen.

Python -Schnittnotation:

a[start:end:step]
  • Zum start und end, negative Werte werden als relativ zum Ende der Sequenz interpretiert.
  • Positive Indizes für end Geben Sie die Position an nach Das letzte Element, das aufgenommen werden muss.
  • Leere Werte werden wie folgt standardmäßig: [+0:-0:1].
  • Die Verwendung eines negativen Schritts kehrt die Interpretation von um start und end

Die Notation erstreckt sich auf (numpy) Matrizen und mehrdimensionale Arrays. Zum Beispiel, um ganze Spalten zu schneiden, können Sie verwenden:

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

Slices enthalten Referenzen, nicht Kopien der Array -Elemente. Wenn Sie eine separate Kopie ein Array erstellen möchten, können Sie verwenden deepcopy().

Sie können auch die Slice -Zuordnung verwenden, um ein oder mehrere Elemente aus einer Liste zu entfernen:

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

So unterrichte ich Neulingen Scheiben:

Verständnis des Unterschieds zwischen Indexierung und Schneiden:

Wiki Python hat dieses erstaunliche Bild, das die Indexierung und Schneiden deutlich unterscheidet.

enter image description here

Es ist eine Liste mit 6 Elementen. Um das Schneiden besser zu verstehen, betrachten Sie diese Liste als ein Satz von sechs zusammengestellten Kästchen. Jede Box enthält ein Alphabet.

Die Indexierung ist wie der Umgang mit dem Inhalt der Box. Sie können den Inhalt eines beliebigen Kontrollkästchens überprüfen. Sie können jedoch nicht den Inhalt mehrerer Kästchen gleichzeitig überprüfen. Sie können sogar den Inhalt der Box ersetzen. Sie können jedoch nicht 2 Kugeln in 1 Box platzieren oder 2 Kugeln gleichzeitig ersetzen.

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

Schneiden ist wie der Umgang mit Kisten selbst. Sie können die erste Box abholen und auf einen anderen Tisch legen. Um die Box abzuholen, müssen Sie nur die Position des Beginns und des Endes der Box wissen.

Sie können sogar die ersten 3 Boxen oder die letzten 2 Boxen oder alle Kisten zwischen 1 und 4 abholen, also können Sie alle Kartons auswählen, wenn Sie anfangen und enden wissen. Diese Positionen werden als Start- und Stopppositionen bezeichnet.

Das Interessante ist, dass Sie mehrere Boxen gleichzeitig ersetzen können. Sie können auch mehrere Kisten platzieren, wo immer Sie möchten.

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

Mit Schritt schneiden:

Bis jetzt haben Sie kontinuierlich Kisten ausgewählt. Aber manchmal müssen Sie diskret abholen. Zum Beispiel können Sie jede zweite Box abholen. Sie können sogar jede dritte Box vom Ende abholen. Dieser Wert wird als Schrittgröße bezeichnet. Dies repräsentiert die Lücke zwischen Ihren aufeinanderfolgenden Pickups. Die Schrittgröße sollte positiv sein, wenn Sie von Anfang bis Ende Boxen auswählen und umgekehrt.

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

Wie Python fehlende Parameter herausfindet:

Wenn Sie einen Parameter auslassen, versucht Python, es automatisch herauszufinden.

Wenn Sie den Quellcode von CPython überprüfen, finden Sie eine Funktion namens PySlice_GetIndiceSex, die Indizes für eine Slice für bestimmte Parameter herausstellt. Hier ist der logische äquivalente Code in Python.

Diese Funktion nimmt ein Python -Objekt und eine optionale Parameter für das Schneiden und Rückgabestart, Stopp, Stufen- und Scheibenlänge für das angeforderte Slice auf.

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)

Dies ist die Intelligenz, die hinter den Scheiben vorhanden ist. Da Python eine integrierte Funktion namens Slice hat, können Sie einige Parameter übergeben und prüfen, wie intelligent die fehlenden Parameter berechnet werden.

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]

Notiz: Dieser Beitrag ist ursprünglich in meinem Blog geschrieben http://www.avilpage.com/2015/03/a-slice-of-python-intelligence-behind.html

Dies gilt nur für einige zusätzliche Informationen ... Betrachten Sie die Liste unten

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

Nur wenige andere Tricks für die Umkehrung der 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]

In der Regel führt das Schreiben von Code mit vielen hartcodierten Indexwerten zu einer Lesbarkeit und Wartungsmesse. Wenn Sie beispielsweise ein Jahr später zum Code zurückkehren, werden Sie es sich ansehen und sich fragen, was Sie gedacht haben, als Sie ihn geschrieben haben. Die gezeigte Lösung ist einfach eine Möglichkeit, deutlicher zu sagen, was Ihr Code tatsächlich tut. Im Allgemeinen erzeugt das eingebaute Slice () ein Slice-Objekt, das überall überall verwendet werden kann, wo eine Scheibe zulässig ist. Zum Beispiel:

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

Wenn Sie eine Slice -Instanz haben, können Sie weitere Informationen darüber erhalten, indem Sie sich die Attribute von s.Start, s.Stop und s.Step ansehen. Zum Beispiel:

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

1. Scheiben Notation

Um es einfach zu machen, denken Sie daran Slice hat nur eine Form:

s[start:end:step]

Und hier ist, wie es funktioniert:

  • s: Ein Objekt, das in Scheiben geschnitten werden kann
  • start: Erster Index, um die Iteration zu starten
  • end: letzter Index, Beachten Sie, dass end Der Index wird nicht in das entstandene Slice aufgenommen
  • step: Wählen Sie alle Elemente aus step Index

Eine andere Importsache: alle start,end, step kann ausgelassen werden! Und wenn sie weggelassen werden, wird ihr Standardwert verwendet: 0,len(s),1 entsprechend.

Mögliche Variationen sind also:

# 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[:]

Hinweis: If start>=end(nur bedenken, wann step>0) Python wird eine leere Scheibe zurückgeben [].

2. Fallstricke

Der obige Teil erklärt die Kernmerkmale der Funktionsweise von Slice, es wird in den meisten Fällen funktionieren. Es kann jedoch Fallstricke geben, die Sie aufsehen sollten, und dieser Teil erklärt sie.

Negative Indizes

Das allererste, was Python -Lernende verwirrt, ist das Index kann negativ sein! Keine Panik: Negativer Index bedeutet, dass sie nach hinten zählen.

Zum Beispiel:

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]

Negativer Schritt

Die Dinge verwirrender machen, ist das step Kann auch negativ sein!

Negativer Schritt bedeutet, das Array rückwärts zu itererieren: Von Ende zu Start, mit dem Endindex und des Startindex ausgeschlossen von Ergebnis.

HINWEIS: Wenn der Schritt negativ ist, der Standardwert für start zu len(s)(während end entspricht nicht gleich 0, Weil s[::-1] enthält s[0]). Zum Beispiel:

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

Out Out Range -Fehler?

Überrascht sein: Slice erhöht keinen IndexError, wenn der Index außerhalb des Bereichs ist!

Wenn der Index außer Reichweite ist, wird Python seinen besten Set den Index aufstellen 0 oder len(s) Nach der Situation. Zum Beispiel:

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. Beispiele

Lassen Sie uns diese Antwort mit Beispielen beenden, was wir besprochen haben:

# 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

Die obigen Antworten diskutieren nicht multi-dimentiertes Array-Slicing, das mit dem berühmten Numpy-Paket möglich ist:

Das Schneiden kann auch auf multi-dimentale Arrays angewendet werden.

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

Das ":2"Bevor Komma in der ersten Dimension und der" arbeitet "0:3:2"Nachdem das Komma in der zweiten Dimension arbeitet.

#!/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 __name__ == '__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)

Sie können dieses Skript ausführen und damit experimentieren. Unten finden Sie einige Muster, die ich aus dem Skript erhalten habe.

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

Beachten Sie bei Verwendung eines negativen Schritts, dass die Antwort um 1 nach rechts verschoben wird.

Mein Gehirn scheint glücklich zu akzeptieren, das zu akzeptieren lst[start:end] enthält die start-D -Artikel. Ich könnte sogar sagen, dass es eine „natürliche Annahme“ ist.

Aber gelegentlich schleicht sich ein Zweifel hinein und mein Gehirn bittet um die Gewissheit, dass es das nicht enthält end-Die Element.

In diesen Momenten verlasse ich mich auf diesen einfachen Satz:

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

Diese hübsche Eigenschaft sagt mir das lst[start:end] enthält das nicht die end-D -Element, weil es in ist lst[end:].

Beachten Sie, dass dieser Satz für jeden zutrifft n überhaupt. Zum Beispiel können Sie das überprüfen

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

kehrt zurück True.

In Python ist die grundlegendste Form für das Schneiden der folgende:

l[start:end]

wo l ist eine Sammlung, start ist ein integrativer Index und end ist ein exklusiver Index.

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]

Wenn Sie vom Start von Start schneiden, können Sie den Null -Index weglassen. Wenn Sie bis zum Ende schneiden, können Sie den endgültigen Index weglassen, da er redundant ist. Seien Sie also nicht ausführlich:

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

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

Negative Ganzzahlen sind nützlich, wenn sie Offsets relativ zum Ende einer Sammlung durchführen:

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]

Es ist möglich, Indizes zu liefern, die beim Schneiden nicht an Grenzen liegen, z. B.:

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]

Denken Sie daran, dass das Ergebnis des Schneidens einer Sammlung eine ganz neue Sammlung ist. Bei Verwendung von Scheibennotation in Zuordnungen muss die Länge der Scheibenzuweisung nicht gleich sein. Die Werte vor und nach dem zugewiesenen Slice werden aufbewahrt, und die Sammlung schrumpft oder wächst, um die neuen Werte zu enthalten:

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]

Wenn Sie den Start- und Endindex weglassen, erstellen Sie eine Kopie der Sammlung:

In [14]: l_copy = l[:]

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

Wenn die Start- und Endindizes bei der Durchführung eines Zuordnungsvorgangs weggelassen werden, wird der gesamte Inhalt der Sammlung durch eine Kopie dessen ersetzt:

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

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

Neben dem grundlegenden Schnitt ist auch die folgende Notation angewendet:

l[start:end:step]

wo l ist eine Sammlung, start ist ein integrativer Index, end ist ein exklusiver Index und step ist ein Schritt, der verwendet werden kann, um jeden zu nehmen nth Artikel in 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]

Verwendung step Bietet einen nützlichen Trick, um eine Sammlung in Python umzukehren:

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

Es ist auch möglich, negative Ganzzahlen für zu verwenden step Als folgendes Beispiel:

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

Verwenden Sie jedoch einen negativen Wert für step könnte sehr verwirrend werden. Um pythonisch pythonisch zu sein, sollten Sie die Verwendung vermeiden start, end, und step in einer einzigen Scheibe. Falls dies erforderlich ist, sollten Sie dies in zwei Aufgaben erledigen (einer zu schneiden und der andere zu Schritt).

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]

Die meisten der oben genannten Antworten beseitigen die Scheibennotation. Die für das Schneiden verwendete erweiterte Indexierungssyntax ist aList[start:stop:step]Grundlegende Beispiele sind

enter image description here:

Weitere Beispiele für Schnitte: 15 verlängerte Scheiben

Das folgende ist das Beispiel eines Index einer Zeichenfolge

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

str="Name string"

Beispiel in Schneiden: [Start: Ende: Schritt

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

Unten finden Sie die Beispielnutzung

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

Ich möchte ein Hello World -Beispiel hinzufügen, das die Grundlagen von Scheiben für die Anfänger erklärt. Es hat mir sehr geholfen.

Lassen Sie uns eine Liste mit sechs Werten haben ['P', 'Y', 'T', 'H', 'O', 'N']:

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

Jetzt sind die einfachsten Scheiben dieser Liste die Unterverminderung. Die Notation ist [<index>:<index>] Und der Schlüssel ist, es so zu lesen:

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

Wenn Sie nun eine Scheibe machen [2:5] Von der obigen Liste wird dies geschehen:

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

Du hast einen Schnitt gemacht Vor das Element mit Index 2 und ein weiterer Schnitt Vor das Element mit Index 5. Das Ergebnis wird also eine Scheibe zwischen diesen beiden Schnitten sein, eine Liste ['T', 'H', 'O'].

Meiner Meinung nach werden Sie die Python -String -Schadensnotation besser verstehen und auswendig lernen, wenn Sie sie auf folgende Weise betrachten (lesen Sie weiter).

Lassen Sie uns mit der folgenden Zeichenfolge arbeiten ...

azString = "abcdefghijklmnopqrstuvwxyz"

Für diejenigen, die es nicht wissen, können Sie ein Substring erstellen azString Verwenden der Notation azString[x:y]

Wenn der gesunde Menschenverstand aus anderen Programmiersprachen stammt, wird der gesunde Menschenverstand beeinträchtigt. Was sind X und Y?

Ich musste mich hinsetzen und mehrere Szenarien in meiner Suche nach einer Auswendiglernentechnik durchführen, die mir hilft, mich daran zu erinnern, was X und Y sind, und mir beim richtigen Versuch richtig in Scheiben schneiden.

Meine Schlussfolgerung ist, dass x und y als die Grenzindizes angesehen werden sollten, die die Saiten umgeben, die wir zusätzlich wollen. Also sollten wir den Ausdruck als sehen azString[index1, index2] oder noch klarer als azString[index_of_first_character, index_after_the_last_character].

Hier ist eine Beispielvisualisierung dieser ...

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

Alles, was Sie tun müssen, wenn Sie Index1 und Index2 auf die Werte festlegen, die das gewünschte Substring umgeben. Um zum Beispiel das Substring "cDEFGH" zu erhalten, können Sie verwenden azString[2:8] Weil der Index auf der linken Seite von "C" 2 beträgt und der auf der rechten Größe von "H" 8 beträgt.

Denken Sie daran, dass wir die Grenzen setzen. Und diese Grenzen sind die Positionen, in denen Sie einige Klammern platzieren können, die um das Substring wie dieses gewickelt werden ...

ab [ CDEFGH ] ij

Dieser Trick funktioniert ständig und ist leicht zu merken.

Wenn Sie das Gefühl haben, dass negative Indizes beim Schneiden verwirrend sind, ist hier eine sehr einfache Möglichkeit, darüber nachzudenken: Ersetzen Sie einfach den negativen Index durch len - index. Ersetzen Sie also beispielsweise -3 durch len(list) - 3.

Der beste Weg, um zu veranschaulichen, was das Schneiden intern tut, ist nur in Code, der diesen Vorgang implementiert:

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

Die grundlegende Schnitttechnik besteht darin, den Ausgangspunkt, den Stopppunkt und die Schrittgröße zu definieren - auch als Schritt bezeichnet.

Zunächst erstellen wir eine Liste von Werten, die in unserem Schnitt verwendet werden sollen.

Erstellen Sie zwei Listen zu Slice, die erste ist eine numerische Liste von 1 bis 9 (Liste A). Die zweite ist auch eine numerische Liste von 0 bis 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)

Index die Nummer 3 aus a und die Nummer 6 von B.

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

Grundlegendes Schneiden

Für das Schneiden verwendete erweiterte Indexierungssyntax ist alist [START: STOP: STEP]. Das Startargument und das Stufenargument sind beide standardmäßig nicht - das einzige erforderliche Argument ist der Stopp. Haben Sie bemerkt, dass dies ähnlich ist, wie der Bereich verwendet wurde, um die Listen A und B zu definieren? Dies liegt daran, dass das Slice -Objekt den Satz der durch Bereich angegebenen Indizes darstellt (Start, Stopp, Schritt). Python 3.4 Dokumentation

Wie Sie sehen können, gibt das Definieren von nur Stop ein Element zurück. Da der Start standardmäßig nicht zu keinem Element endet.

Es ist wichtig zu beachten, dass das erste Element Index 0, nicht Index 1 ist. Deshalb verwenden wir 2 Listen für diese Übung. Die Elemente von List A werden gemäß der ordinalen Position nummeriert (das erste Element ist 1, das zweite Element ist 2 usw.), während die Elemente von Listen B die Zahlen sind, mit denen sie sie indizieren würden ([0] für das erste Element 0 usw. ).

Bei der erweiterten Indexierungssyntax holen wir einen Wertebereich ab. Zum Beispiel werden alle Werte mit einem Dickdarm abgerufen.

A[:]

Um eine Teilmenge von Elementen abzurufen, müssen die Start- und Stopppositionen definiert werden.

Rufen Sie angesichts des Muster -Alists [Start: Stop] die ersten beiden Elemente von Liste A ab

Es ist leicht zu verstehen, ob wir das Schneiden in Beziehung setzen könnten range, was die Indizes gibt. Wir können das Schneiden in die folgenden zwei Kategorien einteilen:


1. Kein Schritt oder Schritt> 0. Zum Beispiel, [i:j] oder [i:j:k] (k> 0)

Angenommen, die Sequenz ist s=[1,2,3,4,5].

  • wenn 0<i<len(s) und 0<j<len(s), dann [i:j:k] -> range(i,j,k)

Zum Beispiel, [0:3:2] -> range(0,3,2) -> 0, 2

  • wenn i>len(s) oder j>len(s), dann i=len(s) oder j=len(s)

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

  • wenn i<0 oder j<0, dann i=max(0,len(s)+i) oder j=max(0,len(s)+j)

Zum Beispiel, [0:-3:2] -> range(0,len(s)-3,2) -> range(0,2,2) -> 0

Für ein anderes Beispiel, [0:-1:2] -> range(0,len(s)-1,2) -> range(0,4,2) -> 0, 2

  • wenn i wird dann nicht angegeben i=0

Zum Beispiel, [:4:2] -> range(0,4,2) -> range(0,4,2) -> 0, 2

  • wenn j wird dann nicht angegeben j=len(s)

Zum Beispiel, [0::2] -> range(0,len(s),2) -> range(0,5,2) -> 0, 2, 4


2. Schritt <0. Zum Beispiel, [i:j:k] (k <0)

Angenommen, die Sequenz ist s=[1,2,3,4,5].

  • wenn 0<i<len(s) und 0<j<len(s), dann [i:j:k] -> range(i,j,k)

Zum Beispiel, [5:0:-2] -> range(5,0,-2) -> 5, 3, 1

  • wenn i>len(s) oder j>len(s), dann i=len(s)-1 oder j=len(s)-1

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

  • wenn i<0 oder j<0, dann i=max(-1,len(s)+i) oder j=max(-1,len(s)+j)

Zum Beispiel, [-2:-10:-2] -> range(len(s)-2,-1,-2) -> range(3,-1,-2) -> 3, 1

  • wenn i wird dann nicht angegeben i=len(s)-1

Zum Beispiel, [:0:-2] -> range(len(s)-1,0,-2) -> range(4,0,-2) -> 4, 2

  • wenn j wird dann nicht angegeben j=-1

Zum Beispiel, [2::-2] -> range(2,-1,-2) -> 2, 0

Für ein anderes Beispiel, [::-1] -> range(len(s)-1,-1,-1) -> range(4,-1,-1) -> 4, 3, 2, 1, 0


Zusammenfassend

enter image description here

Ich denke nicht, dass das das Python Tutorial Das Diagramm (in verschiedenen anderen Antworten zitiert) ist gut, da dieser Vorschlag für positives Schritt funktioniert, jedoch nicht für einen negativen Schritt.

Dies ist das Diagramm:

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

Aus dem Diagramm erwarte ich a[-4,-6,-1] sein yP aber es ist ty.

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

Was immer funktioniert, ist in Zeichen oder Slots zu denken und die Indexierung als halb offenes Intervall zu verwenden-rechts, wenn positiver Schritt, links geöffnet, wenn negativer Schritt.

Auf diese Weise kann ich mir vorstellen a[-4:-6:-1] wie a(-6,-4] in Intervallterminologie.

 +---+---+---+---+---+---+
 | 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  
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top