wake-up-neo.com

Grundlegendes zur Slice-Notation

Ich brauche eine gute Erklärung (Referenzen sind ein Plus) für Pythons Slice-Notation.

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

Es sieht extrem mächtig aus, aber ich habe es nicht richtig verstanden.

2895
Simon

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 den Wert step, der mit einer der folgenden Angaben verwendet werden kann:

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

Der wichtigste Punkt, den Sie sich merken sollten, ist, dass der Wert :stop den ersten Wert darstellt, der im ausgewählten Slice nicht ist. Der Unterschied zwischen stop und start ist also die Anzahl der ausgewählten Elemente (wenn step 1 ist, ist die Standardeinstellung).

Das andere Merkmal ist, dass start oder stop eine negative Zahl sein kann, was bedeutet, dass sie vom Ende des Arrays statt vom Anfang an zählt. Damit:

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

Ebenso kann step 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 Elemente gibt, als Sie verlangen. Wenn Sie beispielsweise nach a[:-2] fragen und a nur ein Element enthält, erhalten Sie eine leere Liste anstelle eines Fehlers. Manchmal bevorzugen Sie den Fehler, daher müssen Sie sich dessen bewusst sein, dass dies passieren kann.

Beziehung zum Objekt slice()

Der Slicing-Operator [] wird im obigen Code tatsächlich mit einem slice() -Objekt unter Verwendung der : -Notation verwendet (die nur innerhalb von [] gültig ist), d.h.

a[start:stop:step]

ist äquivalent zu:

a[slice(start, stop, step)]

Slice-Objekte verhalten sich in Abhängigkeit von der Anzahl der Argumente ähnlich wie range() leicht unterschiedlich, d. H., Es werden sowohl slice(stop) als auch slice(start, stop[, step]) unterstützt. Um die Angabe eines gegebenen Arguments zu überspringen, könnte man None verwenden, so dass z. a[start:] entspricht a[slice(start, None)] oder a[::-1] entspricht a[slice(None, None, -1)].

Während die :-basierte Notation für einfaches Schneiden sehr hilfreich ist, vereinfacht die explizite Verwendung von slice() -Objekten die programmatische Erzeugung von Schneiden.

3910
Greg Hewgill

Das Python-Tutorial spricht darüber (scrollen Sie ein wenig nach unten, bis Sie zu dem Teil über das Schneiden kommen).

Das Grafikdiagramm ASCII ist auch hilfreich, um sich daran zu erinnern, wie Slices 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 Slices funktionieren, besteht darin, sich die Indizes als Zeiger zwischen Zeichen vorzustellen, wobei der linke Rand des ersten Zeichens mit 0 nummeriert ist. Dann der rechte Die Kante des letzten Zeichens einer Zeichenfolge aus n Zeichen hat den Index n .

504
Hans Nowak

Auflisten der Möglichkeiten, die die Grammatik bietet:

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

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

Wenn stride negativ ist, wird die Reihenfolge ein wenig geändert, da wir abwärts 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 Slicing (mit Kommas und Ellipsen) wird meist 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)'
384
ephemient

In den obigen Antworten wird die Slice-Zuweisung nicht erläutert. Um die Slice-Zuweisung zu verstehen, ist es hilfreich, der ASCII -Art ein anderes 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 einen Slice von Null bis n zu denken: "Null ist der Anfang, beginne am Anfang und n Elemente in einer 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 lautet: "Ersetzen Sie für jedes Segment den Anfang durch Null, wenden Sie die vorherige Heuristik an, um das Ende der Liste zu erhalten, und zählen Sie dann die erste Zahl zurück, um die Elemente vom Anfang abzuhacken."

>>> 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 für die Slice-Zuweisung ist, dass seit dem Aufteilen gibt eine Liste, die Slice-Zuweisung erfordert eine Liste (oder eine andere iterierbare):

>>> 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-Zuweisung, die Sie auch oben sehen können, lautet, dass der Teil der Liste, der durch die Slice-Indizierung zurückgegeben wird, derselbe Teil ist, der durch die Slice-Zuweisung geändert wird:

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

Die dritte Regel für die Zuweisung von Slices ist, dass die zugewiesene Liste (iterabel) nicht dieselbe Länge haben muss. Die indizierte Scheibe wird einfach herausgeschnitten und massenweise durch das 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 den man sich gewöhnen muss, ist die Zuordnung zu leeren Slices. Mit Heuristik 1 und 2 ist es einfach, den Kopf herumzukriegen Indizieren 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 wenn Sie das einmal gesehen haben, ist auch die Zuweisung eines Slices zum leeren Slice 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 die zweite Nummer des Slice (4) nicht ändern, immer direkt vor dem 'o' gestapelt werden, auch wenn wir dem leeren Slice zuweisen. Die Position für die leere Schichtzuordnung ist also die logische Erweiterung der Positionen für die nicht leeren Schichtzuordnungen.

Was passiert, wenn Sie mit unserer Prozession fortfahren, den Slice-Anfang hochzuzä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 mit dem Schneiden fertig sind, sind Sie fertig. es beginnt nicht rückwärts zu schneiden. In Python erhalten Sie keine negativen Schritte, es sei denn, Sie fordern sie explizit mit einer negativen Zahl an.

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

Die Regel "Wenn Sie fertig sind, sind Sie fertig" hat einige verrückte Konsequenzen:

>>> 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 Python Slicing im Vergleich zur Indizierung bizarr fehlersicher:

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

Dies kann manchmal nützlich sein, kann aber auch zu etwas merkwürdigem 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 Anwendung ist dies möglicherweise ... oder möglicherweise nicht ... das, was Sie sich dort erhofft haben!


Unten ist der Text meiner ursprünglichen Antwort. Es war für viele nützlich, deshalb 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 dem Schneiden und dem Indizieren verdeutlichen.

283

Erläutern Sie Pythons Slice-Notation

Kurz gesagt, die Doppelpunkte (:) in der tiefgestellten Schreibweise (subscriptable[subscriptarg]) bilden eine Slice-Schreibweise - die die optionalen Argumente start, stop, step enthält:

sliceable[start:stop:step]

Python-Slicing ist eine rechnerisch schnelle Methode, um methodisch auf Teile Ihrer Daten zuzugreifen. Meiner Meinung nach ist es ein Aspekt der Sprache, mit dem man sich auskennen muss, um selbst ein fortgeschrittener Python Programmierer zu sein.

Wichtige Definitionen

Lassen Sie uns zunächst einige Begriffe definieren:

start: der Anfangsindex des Slice, enthält das Element an diesem Index, es sei denn, es ist dasselbe wie stop, Der Standardwert ist 0, dh der erste Index. Wenn dies negativ ist, bedeutet dies, dass n Elemente am Ende beginnen.

stop: der Endindex des Slice, schließt nicht ​​das Element an diesem Index ein, standardmäßig die Länge der Sequenz in Scheiben geschnitten werden, das heißt, bis zum Ende und einschließlich.

Schritt: Der Wert, um den der Index erhöht wird, ist standardmäßig 1. Wenn er negativ ist, wird das Iterable in umgekehrter Reihenfolge durchschnitten.

So funktioniert die Indizierung

Sie können eine dieser positiven oder negativen Zahlen eingeben. Die Bedeutung der positiven Zahlen ist unkompliziert, aber für negative Zahlen zählen Sie genau wie für Indizes in Python vom Ende an rückwärts für start ​​und stop und für - step Sie dekrementieren einfach Ihren Index. Dieses Beispiel ist aus dem Tutorial der Dokumentation , aber ich habe es leicht modifiziert, um anzugeben, auf welches Element in einer Sequenz sich jeder Index bezieht:

 +---+---+---+---+---+---+
 | 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 einschließen, die der Sequenz folgen (die tatsächlich die __getitem__ -Methode der Sequenz implementiert , entsprechend der Python Datenmodell .)

Die Slice-Notation funktioniert folgendermaßen:

sequence[start:stop:step]

Und denken Sie daran, dass es Standardeinstellungen für start, stop und step gibt. Um 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 diese unterstützt, z. B. einer Zeichenfolge) sieht folgendermaßen aus:

my_list[-9:]

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

Erläuterung:

Die vollständige Notation ist

my_list[-9:None:None]

und um die Standardeinstellungen zu ersetzen (tatsächlich, wenn step negativ ist, ist stop die Standardeinstellung -len(my_list) - 1, also None für stop bedeutet wirklich nur, dass es zu dem Endschritt geht, zu dem es geht) :

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

Der Doppelpunkt , :, gibt Python an, dass Sie ein Slice und keinen regulären Index angeben. Deshalb ist die idiomatische Art, eine flache Kopie von Listen in Python 2 zu erstellen, wie folgt:

list_copy = sequence[:]

Und sie zu löschen ist mit:

del my_list[:]

(Python 3 erhält die Methoden list.copy und list.clear.)

Wenn step negativ ist, ändern sich die Standardeinstellungen für start und stop

Wenn das Argument step leer ist (oder None), wird es standardmäßig +1 zugewiesen.

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

Ein negativer Slice ändert also die Standardeinstellungen für start und stop!

Bestätigung in der Quelle

Ich möchte die Benutzer ermutigen, 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 negativ ist:

 step_is_negative = step_sign < 0;

In diesem Fall ist die untere Schranke -1, was bedeutet, dass wir bis einschließlich zum Anfang aufschneiden, und die obere Schranke ist die Länge minus 1, was bedeutet, dass wir am Ende beginnen. (Beachten Sie, dass die Semantik dieses -1verschieden von einem -1 ist, mit dem 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;
}

Andernfalls ist step positiv und die untere Grenze ist Null und die obere Grenze (die wir bis zu der Länge der aufgeschnittenen Liste gehen, aber nicht mit einbeziehen).

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

Dann müssen wir möglicherweise die Standardeinstellungen für start und stop anwenden - die Standardeinstellung für start wird als obere Schranke berechnet, wenn step negativ ist:

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

und stop, die untere Schranke:

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 hilfreich, die Formung des Slice von der Übergabe an die list.__getitem__ -Methode zu trennen ( , wie es die eckigen Klammern tun ). Auch wenn Sie nicht neu darin sind, bleibt Ihr Code besser lesbar, sodass andere, die möglicherweise Ihren Code lesen müssen, besser verstehen können, was Sie tun.

Sie können einer Variablen jedoch nicht einfach ganze Zahlen zuweisen, die durch Doppelpunkte voneinander getrennt sind. Sie müssen das Slice-Objekt verwenden:

last_nine_slice = slice(-9, None)

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

Sie können das Slice-Objekt dann 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 Scheiben nehmen:

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

Speicherüberlegungen:

Da Slices von Python - Listen neue Objekte im Speicher erstellen, ist itertools.islice eine weitere wichtige Funktion, die Sie berücksichtigen sollten. Normalerweise möchten Sie ein Segment durchlaufen und nicht nur statisch im Speicher erstellen. islice ist dafür perfekt. Eine Einschränkung, es werden keine negativen Argumente für start, stop oder step unterstützt. Wenn dies also ein Problem ist, müssen Sie möglicherweise Indizes berechnen oder die Iterationsrate 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 Listen-Slices eine Kopie erstellen, ist ein Merkmal von Listen. Wenn Sie erweiterte Objekte wie einen Pandas DataFrame aufteilen, wird möglicherweise eine Ansicht des Originals und keine Kopie zurückgegeben.

234
Aaron Hall

Und ein paar Dinge, die mir nicht sofort klar 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 aus irgendeinem Grund jeden zweiten Gegenstand in umgekehrter Reihenfolge haben wollten:

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

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 Indexzuweisung 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 abhängig vom Vorzeichen von c (vorwärts oder rückwärts), dass Sie bei a beginnen und bei b enden (ohne Element am b-ten Index). Verwenden Sie die Indexierungsregel oben und denken Sie daran, dass Sie nur Elemente in diesem Bereich finden:

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

Dieser Bereich setzt sich jedoch in beide Richtungen unendlich 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 Auswahl von a, b und c eine Überlappung mit dem obigen Bereich zulässt, während Sie die Regeln für a, b, c verwenden, erhalten Sie entweder eine Liste mit Elementen (die während des Durchlaufs berührt werden) 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]
94
abc

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)
92
AdrianoFerrari

Nachdem ich es ein bisschen benutzt habe, merke ich, dass die einfachste Beschreibung ist, dass es genau das gleiche ist wie die Argumente in einer for -Schleife ...

(from:to:step)

Alle davon sind optional:

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

Dann müssen Sie für die negative Indizierung nur die Länge der Zeichenfolge zu den negativen Indizes hinzufügen, um sie zu verstehen.

Das funktioniert bei mir sowieso ...

59
Simon

Mir fällt es leichter, mich daran zu erinnern, wie es funktioniert, und dann kann ich eine bestimmte Start/Stopp/Schritt-Kombination finden.

Es ist aufschlussreich, zuerst range() zu verstehen:

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 mit start, erhöhen Sie um step, und erreichen Sie stop nicht. Sehr einfach.

Das, woran man sich bei negativen Schritten erinnern sollte, ist, dass stop immer das ausgeschlossene Ende ist, egal ob es höher oder niedriger ist. Wenn Sie dasselbe Stück in umgekehrter Reihenfolge wünschen, ist es viel sauberer, die Umkehrung separat durchzuführen: z. 'abcde'[1:-2][::-1] schneidet ein Zeichen von links, zwei von rechts ab und kehrt dann um. (Siehe auch reversed() .)

Sequence Slicing ist das gleiche, außer dass es zuerst negative Indizes normalisiert und niemals über die Sequenz hinausgeht:

TODO: Der folgende Code hatte einen Fehler mit "nie außerhalb der Sequenz gehen", wenn abs (Schritt)> 1; Ich denke , dass ich es korrigiert habe, 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]

Sorgen Sie sich nicht um die is None Details - denken Sie nur daran, dass das Weglassen von start und/oder stop immer das Richtige tut, um Ihnen die gesamte Sequenz zu geben.

Durch die erstmalige Normalisierung negativer Indizes 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, beachte jedoch, dass sie die Länge nur einmal hinzufügt: z. 'abcde'[-53:42] ist nur die ganze Zeichenfolge.

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 wird Ihnen helfen, die Liste in Python zu modellieren.

Referenz: http://wiki.python.org/moin/MovingToPythonFromOtherLanguages

37
xiaoyu

Ich benutze die Methode "Ein Index zwischen Elementen", um selbst darüber nachzudenken, aber eine Art, es zu beschreiben, die manchmal anderen hilft, es zu verstehen, ist die folgende:

mylist[X:Y]

X ist der Index des ersten gewünschten Elements.
Y ist der Index des ersten Elements, das Sie nicht möchten.

36
Steve Losh

Python-Slicing-Notation:

a[start:end:step]
  • Bei start und end werden negative Werte als relativ zum Ende der Sequenz interpretiert.
  • Positive Indizes für end geben die Position nach dem letzten einzuschließenden Element an.
  • Standardmäßig sind leere Werte wie folgt angegeben: [+0:-0:1].
  • Die Verwendung eines negativen Schritts kehrt die Interpretation von start und end um.

Die Notation erstreckt sich auf (numpy) Matrizen und mehrdimensionale Arrays. Zum Schneiden ganzer Spalten können Sie beispielsweise Folgendes verwenden:

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

Slices enthalten Referenzen, keine Kopien der Array-Elemente. Wenn Sie ein Array separat kopieren möchten, können Sie deepcopy() verwenden.

35
nobar

So unterrichte ich Neulingen Slices:

Unterschied zwischen Indizieren und Schneiden verstehen:

Wiki Python hat dieses erstaunliche Bild, das Indexing und Slicing klar voneinander unterscheidet.

enter image description here

Es ist eine Liste mit 6 Elementen. Um das Schneiden besser zu verstehen, betrachten Sie diese Liste als einen Satz von sechs Kästchen, die zusammengesetzt sind. In jeder Box befindet sich ein Alphabet.

Indizieren ist wie mit dem Inhalt von box umzugehen. Sie können den Inhalt jedes Kä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 Bälle in eine Schachtel legen oder 2 Bälle 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 mit Boxen selbst umzugehen. Sie können die erste Kiste abholen und auf einen anderen Tisch stellen. Um die Box abzuholen, müssen Sie lediglich die Position von Anfang und Ende der Box kennen.

Sie können sogar die ersten 3 Boxen oder die letzten 2 Boxen oder alle Boxen zwischen 1 und 4 abholen. Sie können also eine beliebige Gruppe von Boxen auswählen, wenn Sie Anfang und Ende kennen. Diese Positionen werden als Start- und Stoppositionen bezeichnet.

Das Interessante ist, dass Sie mehrere Kartons gleichzeitig ersetzen können. Sie können auch mehrere Boxen 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']

Schneiden mit Schritt:

Sie haben bisher ununterbrochen Kisten gepflückt. Aber manchmal müssen Sie diskret abholen. Zum Beispiel können Sie jede zweite Box abholen. Sie können sogar jede dritte Kiste vom Ende abholen. Dieser Wert wird als Schrittweite bezeichnet. Dies stellt die Lücke zwischen Ihren aufeinanderfolgenden Abholungen dar. Die Schrittgröße sollte positiv sein, wenn Sie Kästchen von Anfang bis Ende und umgekehrt auswählen.

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

Wenn Sie beim Schneiden einen Parameter weglassen, versucht Python, diesen automatisch zu ermitteln.

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

Diese Funktion verwendet ein Python -Objekt und optionale Parameter zum Schneiden und gibt Start, Stopp, Schritt und Schnittlänge für den angeforderten Schnitt zurück.

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 Scheiben steckt. Da Python eine eingebaute Funktion namens slice hat, können Sie einige Parameter übergeben und überprüfen, wie intelligent es fehlende Parameter berechnet.

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]

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

32
ChillarAnand

Sie können auch die Slice-Zuweisung 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]
32
dansalmo

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

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

Einige andere Tricks zum Umkehren 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]
31

In der Regel führt das Schreiben von Code mit vielen fest codierten Indexwerten zu Lesbarkeits- und Wartungsproblemen. Wenn Sie beispielsweise ein Jahr später zum Code zurückkehren, werden Sie sich den Code ansehen und sich fragen, was Sie gedacht haben, als Sie ihn geschrieben haben. Die gezeigte Lösung ist einfach eine Möglichkeit, klarer zu sagen, was Ihr Code tatsächlich tut. Im Allgemeinen erstellt die integrierte Funktion slice () ein Slice-Objekt, das überall dort verwendet werden kann, wo ein Slice 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 s haben, können Sie weitere Informationen dazu erhalten, indem Sie sich die Attribute s.start, s.stop und s.step ansehen. Zum Beispiel:

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

1. Slice-Notation

Denken Sie zur Vereinfachung an Slice hat nur eine Form :

s[start:end:step]

und so funktioniert es:

  • s: Ein Objekt, das in Scheiben geschnitten werden kann
  • start: Erster Index, der die Iteration startet
  • end: letzter Index, BITTE BEACHTEN SIE, dass der Index end nicht im resultierenden Slice enthalten ist
  • step: Wähle das Element für jeden step Index

Eine andere wichtige Sache: alle start, end, step können weggelassen 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: Wenn start>=end (nur wenn step>0 berücksichtigt wird), gibt python ein leeres Stück [] zurück.

2. Fallstricke

Im obigen Teil werden die wichtigsten Funktionen für die Funktionsweise von Slices erläutert, die in den meisten Fällen funktionieren. Es kann jedoch Fallstricke geben, auf die Sie achten sollten, und dieser Teil erklärt sie.

Negative Indizes

Das allererste, was die python Lernenden verwirrt, ist, dass Index kann negativ sein! Keine Panik: negativer Index bedeutet Rückwärtszählung.

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

Verwirrender ist, dass step auch negativ sein kann!

Negativer Schritt bedeutet, dass das Array rückwärts durchlaufen wird: von Ende zu Anfang mit eingeschlossenem Endindex und vom Ergebnis ausgeschlossenem Startindex.

NOTE: Wenn step negativ ist, ist der Standardwert für start bis len(s) (während end nicht gleich 0 ist, 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

Fehler außerhalb des Bereichs?

Seien Sie überrascht: Slice löst IndexError nicht aus, wenn der Index außerhalb des Bereichs liegt!

Wenn der Index außerhalb des gültigen Bereichs liegt, versucht python, den Index je nach Situation auf 0 oder len(s) zu setzen. 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 abschließen, die alles erklären, 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
26
cizixs

Die obigen Antworten behandeln nicht das mehrdimensionale Array-Slicing, das mit dem berühmten NumPy-Paket möglich ist:

Das Schneiden kann auch auf mehrdimensionale 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" vor dem Komma wirkt auf die erste Dimension und das "0:3:2" nach dem Komma auf die zweite Dimension.

20
Statham

Mein Gehirn scheint glücklich zu sein, zu akzeptieren, dass lst[start:end] den start-ten Gegenstand enthält. Ich könnte sogar sagen, dass es eine "natürliche Annahme" ist.

Aber gelegentlich schleicht sich ein Zweifel ein und mein Gehirn bittet um Bestätigung, dass es nicht das end -te Element enthält.

In diesen Momenten verlasse ich mich auf diesen einfachen Satz:

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

Diese hübsche Eigenschaft sagt mir, dass lst[start:end] nicht das end- te Element enthält, da es sich in lst[end:] befindet.

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

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

gibt True zurück.

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)

Sie können dieses Skript ausführen und damit experimentieren. Nachfolgend finden Sie einige Beispiele, 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 ist.

14
mahmoh

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

l[start:end]

wobei l eine Sammlung ist, start ein inklusiver Index ist und end ein exklusiver Index ist.

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 von Anfang an schneiden, können Sie den Nullindex weglassen, und wenn Sie bis zum Ende schneiden, können Sie den endgültigen Index weglassen, da er redundant ist. Seien Sie also nicht wortreich:

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 Offsets relativ zum Ende einer Sammlung ausgeführt werden:

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 bereitzustellen, die beim Schneiden außerhalb der Grenzen liegen, wie z.

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 Aufteilens einer Sammlung eine völlig neue Sammlung ist. Wenn Sie die Slice-Notation in Zuweisungen verwenden, muss die Länge der Slice-Zuweisung nicht identisch sein. Die Werte vor und nach dem zugewiesenen Segment werden beibehalten, und die Sammlung wird verkleinert oder vergrößert, 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 der Start- und der Endindex bei einer Zuweisungsoperation weggelassen werden, wird der gesamte Inhalt der Sammlung durch eine Kopie der referenzierten Elemente ersetzt:

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

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

Neben dem einfachen Schneiden kann auch die folgende Notation angewendet werden:

l[start:end:step]

wobei l eine Sammlung ist, start ein inklusiver Index ist, end ein exklusiver Index ist und step ein Schritt ist, der verwendet werden kann, um alle n-te Element 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]

Die Verwendung von 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 step als folgendes Beispiel zu verwenden:

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

Die Verwendung eines negativen Werts für step kann jedoch sehr verwirrend werden. Um pythonisch zu sein, sollten Sie außerdem die Verwendung von start, end und step in einem einzigen Slice vermeiden. Wenn dies erforderlich ist, sollten Sie dies in zwei Aufgaben tun (eine zum Schneiden und die andere zum Schreiten).

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

Die meisten der obigen Antworten klären die Slice-Notation. Die erweiterte Indizierungssyntax für das Slicing lautet aList[start:stop:step]

enter image description here :

Weitere Beispiele für das Schneiden: 15 Extended Slices

11
Roshan Bagdiya

Das Folgende ist das Beispiel für den Index einer Zeichenfolge

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

str="Name string"

slicing-Beispiel: [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 sehen Sie das Anwendungsbeispiel

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

Meiner Meinung nach werden Sie die Python - Aufteilungsnotation für Strings besser verstehen und auswendig lernen, wenn Sie sie wie folgt betrachten (lesen Sie weiter).

Lass uns mit dem folgenden String arbeiten ...

azString = "abcdefghijklmnopqrstuvwxyz"

Für diejenigen, die es nicht wissen, können Sie jeden Teilstring aus azString mit der Notation azString[x:y] erstellen.

Wenn man aus anderen Programmiersprachen kommt, wird der gesunde Menschenverstand gefährdet. Was sind x und y?

Ich musste mich hinsetzen und verschiedene Szenarien ausführen, um eine Memorisierungstechnik zu finden, die mir hilft, mich an x ​​und y zu erinnern und die Saiten beim ersten Versuch richtig zu schneiden.

Meine Schlussfolgerung ist, dass x und y als die Grenzindizes angesehen werden sollten, die die Zeichenfolgen umgeben, die wir extrahieren möchten. Also sollten wir den Ausdruck als azString[index1, index2] oder noch deutlicher als azString[index_of_first_character, index_after_the_last_character] sehen.

Hier ist eine Beispielvisualisierung davon ...

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, um index1 und index2 auf die Werte zu setzen, die die gewünschte Teilzeichenfolge umgeben. Um beispielsweise die Teilzeichenfolge "cdefgh" abzurufen, können Sie azString[2:8] verwenden, da der Index auf der linken Seite von "c" 2 und der auf der rechten Seite von "h" 8 ist.

Denken Sie daran, dass wir die Grenzen setzen. Und diese Grenzen sind die Positionen, an denen Sie einige Klammern platzieren können, die wie folgt um die Teilzeichenfolge gewickelt werden ...

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

Dieser Trick funktioniert die ganze Zeit und ist leicht zu merken.

8
asiby

Ich möchte ein Hello World-Beispiel hinzufügen, das die Grundlagen von Slices für 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 

Nun sind die einfachsten Teile dieser Liste ihre Unterlisten. 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 einen Slice [2:5] aus der obigen Liste erstellen, geschieht Folgendes:

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

Sie haben einen Schnitt gemacht vor das Element mit dem Index 2 und einen weiteren Schnitt vor das Element mit dem Index 5. Das Ergebnis ist also eine Scheibe zwischen diesen beiden Schnitten, eine Liste ['T', 'H', 'O'].

7
Jeyekomon

Wenn Sie der Meinung sind, dass negative Indizes beim Slicing verwirrend sind, können Sie dies ganz einfach überdenken: Ersetzen Sie den negativen Index einfach durch len - index. Ersetzen Sie zum Beispiel -3 durch len(list) - 3.

Der beste Weg, um zu veranschaulichen, was das Schneiden intern bewirkt, besteht darin, es in Code zu zeigen, der diese Operation 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)]
5
Shital Shah

Slice : - Schlange erscheint in der Nähe Ihres Fußes. Es bewegt sich vom Unsichtbaren zum Sichtbaren. Unsere Vision enthüllt (wie eine Scheibe) nur einen Teil der Welt. In ähnlicher Weise extrahiert ein Python -Slice Elemente basierend auf einem Start und einem Stopp. In Python nehmen wir verschiedene Arten von Slices auf. Wir geben einen optionalen ersten Index, einen optionalen letzten Index und einen optionalen Schritt an.

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.

gute Beispiele finden Sie unter folgendem Link: - Beispiel für Python-Slice-Notation

4
SHASHI BHUSAN

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

Zunächst erstellen wir eine Liste mit Werten, die für unser Slicing verwendet werden sollen.

Erstellen Sie zwei Listen zum Schneiden. Die erste ist eine numerische Liste von 1 bis 9 (Liste A). Die zweite ist ebenfalls 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)

Indizieren Sie die Nummer 3 von A und die Nummer 6 von B.

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

Basic Slicing

Die erweiterte Indizierungssyntax für das Slicing lautet aList [start: stop: step]. Sowohl das Startargument als auch das Schrittargument haben standardmäßig den Wert none. Das einzige erforderliche Argument ist stop. Ist Ihnen aufgefallen, dass dies in etwa der Fall ist, als der Bereich zur Definition der Listen A und B verwendet wurde? Dies liegt daran, dass das Slice-Objekt die durch range (start, stop, step) angegebene Menge von Indizes darstellt. Python 3.4 Dokumentation

Wie Sie sehen, gibt die Definition von nur Stopp ein Element zurück. Da der Standardwert für start none ist, wird nur ein Element abgerufen.

Es ist wichtig zu beachten, dass das erste Element der Index 0 und NICHT der Index 1 ist. Aus diesem Grund verwenden wir für diese Übung 2 Listen. Die Elemente von Liste A werden entsprechend der Ordnungszahl nummeriert (das erste Element ist 1, das zweite Element ist 2 usw.), während die Elemente von Liste B die Nummern sind, mit denen sie indiziert werden ([0] für das erste Element 0 usw.) ).

Mit der erweiterten Indizierungssyntax rufen wir einen Wertebereich ab. Beispielsweise werden alle Werte mit einem Doppelpunkt abgerufen.

A[:]

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

Rufen Sie unter Berücksichtigung des Musters aList [start: stop] die ersten beiden Elemente aus Liste A ab

4

Es ist leicht zu verstehen, ob wir Slicing mit range in Beziehung setzen könnten, das die Indizes liefert. 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 nicht angegeben ist, dann i=0

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

  • wenn j nicht angegeben ist, dann 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 nicht angegeben ist, dann i=len(s)-1

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

  • wenn j nicht angegeben ist, dann 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


In Summe

enter image description here

2
Banghua Zhao

Ich denke nicht, dass das Diagramm Python-Tutorial (in verschiedenen anderen Antworten zitiert) gut ist, da dieser Vorschlag für einen positiven Schritt funktioniert, aber 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, dass a[-4,-6,-1]yP ist, 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 Indizierung als halboffenes Intervall zu verwenden - rechts offen, wenn der Schritt positiv ist, links offen, wenn der Schritt negativ ist.

Auf diese Weise kann ich a[-4:-6:-1] als a(-6,-4] in Intervallterminologie betrachten.

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

Ich war ein wenig frustriert darüber, dass ich keine Online-Quelle oder Python -Dokumentation gefunden habe, die genau beschreibt, was das Schneiden bewirkt.

Ich nahm den Vorschlag von Aaron Hall an und las die relevanten Teile des CPython-Quellcodes. Dann schrieb ich einen Python -Code, der das Schneiden ähnlich wie in CPython ausführt. Ich habe meinen Code in Python 3 mit Millionen von Zufallstests für Ganzzahllisten getestet.

Möglicherweise finden Sie in meinem Code hilfreiche Verweise auf die relevanten Funktionen in 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

Ich persönlich denke darüber nach wie eine for-Schleife

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

Beachten Sie auch, dass negative Werte für start und end relativ zum Ende der Liste sind.

0
Raman