Antworten:
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 step
Wert, der mit einem der oben genannten Werte verwendet werden kann:
a[start:stop:step] # start through not past stop, by step
Der wichtigste Punkt, an den Sie sich erinnern sollten, ist, dass der :stop
Wert den ersten Wert darstellt, der sich nicht im ausgewählten Slice befindet. Der Unterschied zwischen stop
und start
ist also die Anzahl der ausgewählten Elemente (wenn step
1 ist, die Standardeinstellung).
Das andere Merkmal ist, dass start
oder stop
kann eine negative Zahl sein, was bedeutet, dass sie vom Ende des Arrays statt vom Anfang 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 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 Elemente gibt, als Sie verlangen. Wenn Sie beispielsweise nach einem Element fragen a[:-2]
und es a
nur enthalten, erhalten Sie anstelle eines Fehlers eine leere Liste. Manchmal würden Sie den Fehler bevorzugen, daher müssen Sie sich bewusst sein, dass dies passieren kann.
slice()
ObjektDer Slicing-Operator []
wird im obigen Code tatsächlich mit einem slice()
Objekt verwendet, das die :
Notation verwendet (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 ebenfalls leicht unterschiedlich, ähnlich wie range()
beide, slice(stop)
und slice(start, stop[, step])
werden unterstützt. Um die Angabe eines bestimmten Arguments zu überspringen, könnte man verwenden None
, so dass zB a[start:]
äquivalent zu a[slice(start, None)]
oder a[::-1]
äquivalent zu ist a[slice(None, None, -1)]
.
Während die :
Notation auf Basis des einfachen Schneidens sehr hilfreich ist, slice()
vereinfacht die explizite Verwendung von Objekten die programmatische Erzeugung des Schneidens.
None
jeden der leeren Räume ersetzen . Zum Beispiel [None:None]
macht eine ganze Kopie. Dies ist nützlich, wenn Sie das Ende des Bereichs mithilfe einer Variablen angeben und das letzte Element einschließen müssen.
del
der Schriftart-Notation hinzuzufügen . Insbesondere del arr[:]
ist nicht sofort offensichtlich ("arr [:] macht eine Kopie, löscht del diese Kopie ???" usw.)
Das Python-Tutorial spricht darüber (scrollen Sie ein wenig nach unten, bis Sie zu dem Teil über das Schneiden kommen).
Das ASCII-Grafikdiagramm 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 so vorzustellen, dass sie zwischen Zeichen zeigen, wobei der linke Rand des ersten Zeichens mit 0 nummeriert ist. Dann hat der rechte Rand des letzten Zeichens einer Zeichenfolge mit n Zeichen den Index n .
a[-4,-6,-1]
, yP
aber es ist ty
. Was immer funktioniert, ist, in Zeichen oder Slots zu denken und die Indizierung als halboffenes Intervall zu verwenden - rechts offen, wenn positiver Schritt, links offen, wenn negativer Schritt.
x[:0]
dies beim Anfang der Fall ist), sodass Sie kleine Arrays in Sonderfällen erstellen müssen. : /
Aufzählung der Möglichkeiten der Grammatik:
>>> 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 ja (high-low)%stride != 0
, dann ist der Endpunkt natürlich etwas niedriger als high-1
.
Wenn stride
negativ, wird die Reihenfolge etwas geändert, da wir herunterzä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 Grundsequenzen 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)'
repr
__getitem__
ist; Ihr Beispiel entspricht apple[slice(4, -4, -1)]
.
In den obigen Antworten wird die Slice-Zuweisung nicht erläutert. Um die Slice-Zuweisung zu verstehen, ist es hilfreich, der ASCII-Grafik 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 ein Slice von Null bis n zu denken: "Null ist der Anfang, beginnen Sie am Anfang und nehmen Sie 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 lautet: "Ersetzen Sie für jedes Slice 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 Elemente vom Anfang zu entfernen."
>>> 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 lautet, dass für die Slice-Zuweisung eine Liste (oder eine andere iterierbare) erforderlich ist, da das Slicing eine Liste zurückgibt :
>>> 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 jeder 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 Slice-Zuweisung lautet, dass die zugewiesene Liste (iterierbar) nicht dieselbe Länge haben muss. Das indizierte Slice wird einfach herausgeschnitten und massenhaft 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 Scheiben. Mit Heuristik 1 und 2 können Sie ganz einfach ein leeres Slice indizieren :
>>> 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 gesehen haben, ist auch die Slice-Zuordnung 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
Da wir die zweite Nummer des Slice (4) nicht ändern, stapeln sich die eingefügten Elemente immer direkt gegen das 'o', selbst wenn wir dem leeren Slice zuweisen. Die Position für die Zuweisung leerer Slices ist also die logische Erweiterung der Positionen für die Zuweisungen nicht leerer Slices.
Was passiert, wenn Sie mit unserer Prozession fortfahren, den Beginn der Scheibe 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 fragen explizit nach ihnen, indem Sie eine negative Zahl verwenden.
>>> p[5:3:-1]
['n','o']
Die Regel "Sobald Sie fertig sind, sind Sie fertig" hat einige seltsame 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
Tatsächlich ist Python-Slicing im Vergleich zur Indizierung bizarr fehlersicher:
>>> p[100:200]
[]
>>> p[int(2e99):int(1e99)]
[]
Dies kann manchmal nützlich sein, aber 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 Anwendung könnte das ... oder auch nicht ... das sein, was Sie sich dort erhofft haben!
Unten ist der Text meiner ursprünglichen Antwort. Es war für viele Leute 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 Schneiden und Indizieren verdeutlichen.
Erklären Sie Pythons Slice-Notation
Kurz gesagt, die Doppelpunkte ( :
) in der Index - Notation ( subscriptable[subscriptarg]
) make Slice - Notation - , die die optionalen Argumente haben, start
, stop
, step
:
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 vertraut sein muss, um selbst ein fortgeschrittener Python-Programmierer zu sein.
Lassen Sie uns zunächst einige Begriffe definieren:
start: Der Anfangsindex des Slice enthält das Element an diesem Index, sofern es nicht mit stop identisch ist. Der Standardwert ist 0, dh der erste Index. Wenn es negativ ist, bedeutet dies, dass die
n
Elemente am Ende beginnen.stop: Der Endindex des Slice enthält nicht das Element an diesem Index. Die Standardeinstellung ist die Länge der geschnittenen Sequenz, dh bis einschließlich des Endes.
Schritt: Der Betrag, um den der Index erhöht wird, ist standardmäßig 1. Wenn er negativ ist, schneiden Sie in umgekehrter Reihenfolge über das Iterable.
Sie können jede dieser positiven oder negativen Zahlen eingeben. Die Bedeutung der positiven Zahlen ist unkompliziert, aber für negative Zahlen zählen Sie wie für Indizes in Python vom Ende an für Start und Stopp rückwärts und für den Schritt dekrementieren Sie einfach Ihren Index. Dieses Beispiel stammt 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
Um die Slice-Notation mit einer Sequenz zu verwenden, die dies unterstützt, müssen Sie mindestens einen Doppelpunkt in die eckigen Klammern setzen, die der Sequenz folgen (die die Methode der Sequenz gemäß dem Python-Datenmodell tatsächlich implementieren__getitem__
).
Die Slice-Notation funktioniert folgendermaßen:
sequence[start:stop:step]
Und denken Sie daran, dass es Standardeinstellungen für Start , Stopp und Schritt gibt. Um auf die Standardeinstellungen zuzugreifen, lassen Sie das Argument einfach weg.
Die Slice-Notation zum Abrufen der letzten neun Elemente aus einer Liste (oder einer anderen Sequenz, die dies unterstützt, z. B. eine 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 verkürze ich es mental als "-9, on")
Die vollständige Notation ist
my_list[-9:None:None]
und um die Standardeinstellungen zu ersetzen (tatsächlich, wenn sie step
negativ sind, ist stop
die Standardeinstellung -len(my_list) - 1
, also None
bedeutet Stop wirklich nur, dass es zu dem Endschritt geht, zu dem es führt):
my_list[-9:len(my_list):1]
Der Doppelpunkt , :
ist, was Python sagt Sie , ihm ein Stück und nicht einen regulären Index sind zu geben. Aus diesem Grund ist die idiomatische Art, eine flache Kopie von Listen in Python 2 zu erstellen, die folgende
list_copy = sequence[:]
Und sie zu löschen ist mit:
del my_list[:]
(Python 3 erhält eine list.copy
und list.clear
Methode.)
step
negativ ist, ändern sich die Standardeinstellungen start
und stop
ändern sichWenn das step
Argument leer (oder None
) ist, wird es standardmäßig zugewiesen +1
.
Sie können jedoch eine negative Ganzzahl übergeben, und die Liste (oder die meisten anderen Standard-Slicables) wird vom Ende bis zum Anfang aufgeteilt.
Somit ändert ein negativer Slice die Standardeinstellungen für start
undstop
!
Ich möchte Benutzer dazu ermutigen, sowohl die Quelle als auch die Dokumentation zu lesen. Den Quellcode für Slice-Objekte und diese Logik finden Sie hier . Zuerst bestimmen wir, ob step
negativ ist:
step_is_negative = step_sign < 0;
Wenn ja, bedeutet die Untergrenze, -1
dass wir bis zum Anfang schneiden, und die Obergrenze ist die Länge minus 1, was bedeutet, dass wir am Ende beginnen. (Beachten Sie, dass die Semantik dies -1
ist unterschiedlich von einem , -1
dass die Benutzer - Indizes in Python passieren kann das letzte Element angezeigt wird .)
if (step_is_negative) { lower = PyLong_FromLong(-1L); if (lower == NULL) goto error; upper = PyNumber_Add(length, lower); if (upper == NULL) goto error; }
Andernfalls step
ist es positiv, und die Untergrenze ist Null und die Obergrenze (bis zu der wir gehen, aber nicht einschließen) die Länge der geschnittenen Liste.
else { lower = _PyLong_Zero; Py_INCREF(lower); upper = length; Py_INCREF(upper); }
Dann müssen wir möglicherweise die Standardeinstellungen für start
und anwenden stop
- der Standardwert für start
wird dann als Obergrenze berechnet, wenn er step
negativ ist:
if (self->start == Py_None) { start = step_is_negative ? upper : lower; Py_INCREF(start); }
und stop
die Untergrenze:
if (self->stop == Py_None) { stop = step_is_negative ? lower : upper; Py_INCREF(stop); }
Es kann nützlich sein, das Slice von der Übergabe an die list.__getitem__
Methode zu trennen ( genau das tun die eckigen Klammern ). Selbst wenn Sie nicht neu darin sind, bleibt Ihr Code besser lesbar, sodass andere, die Ihren Code möglicherweise lesen müssen, besser 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 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)
Da Scheiben Python - Listen neue Objekte im Speicher zu erstellen, in einer anderen wichtige Funktion bewusst ist , zu sein itertools.islice
. Normalerweise möchten Sie über ein Slice iterieren und es nicht nur statisch im Speicher erstellen lassen. islice
ist perfekt dafür. Ein Vorbehalt, es unterstützt nicht die negativen Argumente start
, stop
oder step
, also , wenn das ein Problem ist Sie benötigen Indizes berechnen oder den iterable im Voraus zu 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 der Listen selbst. Wenn Sie erweiterte Objekte wie einen Pandas DataFrame in Scheiben schneiden, wird möglicherweise eine Ansicht des Originals und keine Kopie zurückgegeben.
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 Punkt in umgekehrter Reihenfolge wollten:
>>> 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 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), beginnen Sie bei a und enden Sie bei b (ohne Element am b-ten Index). Verwenden Sie die obige Indizierungsregel 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 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 Auswahl von a, b und c eine Überlappung mit dem obigen Bereich beim Durchlaufen unter Verwendung der Regeln für a, b, c oben zulässt, erhalten Sie entweder eine Liste mit Elementen (die während des Durchlaufs berührt werden) oder 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]
a = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]; a[:-2:-2]
was zu[9]
Ich habe diese großartige Tabelle unter http://wiki.python.org/moin/MovingToPythonFromOtherLanguages gefunden
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 wenig benutzt habe, stelle ich fest, dass die einfachste Beschreibung ist, dass es genau das gleiche ist wie die Argumente in einer for
Schleife ...
(from:to:step)
Alle sind optional:
(:to:step)
(from::step)
(from:to)
Für die negative Indizierung müssen Sie nur die Länge der Zeichenfolge zu den negativen Indizes hinzufügen, um sie zu verstehen.
Das funktioniert sowieso bei mir ...
Es fällt mir leichter, mich daran zu erinnern, wie es funktioniert, und dann kann ich eine bestimmte Kombination aus Start, Stopp und Schritt herausfinden.
Es ist lehrreich, range()
zuerst 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
, erreichen Sie nicht stop
. Sehr einfach.
Die Sache, an die man sich beim negativen Schritt erinnern sollte, ist, dass stop
immer das ausgeschlossene Ende ist, egal ob es höher oder niedriger ist. Wenn Sie dasselbe Slice in umgekehrter Reihenfolge möchten, ist es viel sauberer, die Umkehrung separat durchzuführen: z. B. 'abcde'[1:-2][::-1]
schneidet ein Zeichen von links, zwei von rechts ab und kehrt dann um. (Siehe auch reversed()
.)
Das Sequenz-Slicing ist dasselbe, außer dass es zuerst negative Indizes normalisiert und niemals außerhalb der Sequenz liegen kann:
TODO : Der folgende Code hatte einen Fehler mit "nie außerhalb der Sequenz gehen", wenn abs (Schritt)> 1; Ich glaube, ich habe es gepatcht, um es richtig zu machen, 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]
Machen Sie sich keine Sorgen um die is None
Details - denken Sie daran, dass das Weglassen start
und / oder stop
immer das Richtige tut, um Ihnen die gesamte Sequenz zu geben.
Wenn Sie zuerst die negativen Indizes normalisieren, 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 die Länge nur einmal hinzugefügt 'abcde'[-53:42]
wird : zB ist nur die gesamte Zeichenfolge.
this_is_how_slicing_works
ist nicht dasselbe wie Python Slice. EG [0, 1, 2][-5:3:3]
wird [0] in Python erhalten, aber list(this_is_how_slicing_works([0, 1, 2], -5, 3, 3))
[1].
range(4)[-200:200:3] == [0, 3]
aber list(this_is_how_slicing_works([0, 1, 2, 3], -200, 200, 3)) == [2]
. Mein if 0 <= i < len(seq):
Versuch war, "nie außerhalb der Sequenz gehen" einfach zu implementieren, ist aber für Schritt> 1 falsch. Ich werde es später heute umschreiben (mit Tests).
Ich benutze die Methode "Ein Index zeigt zwischen Elementen", um selbst darüber nachzudenken, aber eine Art, es zu beschreiben, die manchmal anderen hilft, es zu bekommen, ist 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.
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
Python-Slicing-Notation:
a[start:end:step]
start
und end
werden negative Werte als relativ zum Ende der Sequenz interpretiert.end
geben die Position danach an dem letzten Element an, das aufgenommen werden soll.[+0:-0:1]
.start
und umend
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 Verweise und keine Kopien der Array-Elemente. Wenn Sie eine separate Kopie eines Arrays erstellen möchten, können Sie diese verwenden deepcopy()
.
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]
So bringe ich Neulingen Scheiben bei:
Den Unterschied zwischen Indizieren und Schneiden verstehen:
Wiki Python hat dieses erstaunliche Bild, das Indizierung und Slicing klar unterscheidet.
Es ist eine Liste mit sechs Elementen. Um das Schneiden besser zu verstehen, betrachten Sie diese Liste als einen Satz von sechs Feldern, die zusammen angeordnet sind. Jede Box enthält ein Alphabet.
Die Indizierung ist wie der Umgang mit dem Inhalt der Box. Sie können den Inhalt eines beliebigen 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 zwei Bälle in eine Schachtel legen oder zwei 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
Das Schneiden ist wie der Umgang mit Kisten selbst. Sie können die erste Schachtel aufheben und auf einen anderen Tisch stellen. Um die Box aufzunehmen, müssen Sie lediglich die Position von Anfang und Ende der Box kennen.
Sie können sogar die ersten drei Felder oder die letzten beiden Felder oder alle Felder zwischen 1 und 4 auswählen. Sie können also einen beliebigen Satz von Feldern auswählen, wenn Sie den Anfang und das Ende kennen. Diese Positionen werden als Start- und Stopppositionen bezeichnet.
Das Interessante ist, dass Sie mehrere Boxen gleichzeitig ersetzen können. Sie können auch mehrere Felder 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:
Bis jetzt haben Sie fortlaufend 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 am Ende abholen. Dieser Wert wird als Schrittgröße bezeichnet. Dies stellt die Lücke zwischen Ihren aufeinanderfolgenden Tonabnehmern dar. Die Schrittgröße sollte positiv sein, wenn Sie Kästchen von Anfang bis Ende 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 beim Schneiden einen Parameter weglassen, versucht Python, ihn automatisch herauszufinden.
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 ermittelt. Hier ist der logisch äquivalente Code in Python.
Diese Funktion verwendet ein Python-Objekt und optionale Parameter für das Slicing und gibt die Start-, Stopp-, Schritt- und Slice-Länge für das angeforderte Slice 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 vorhanden ist. Da Python über eine integrierte Funktion namens Slice verfügt, können Sie einige Parameter übergeben und überprüfen, wie intelligent fehlende 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]
Hinweis: Dieser Beitrag wurde ursprünglich in meinem Blog The Intelligence Behind Python Slices geschrieben .
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 auf den Code zurückkommen, werden Sie ihn sich ansehen und sich fragen, was Sie gedacht haben, als Sie ihn geschrieben haben. Die gezeigte Lösung ist lediglich eine Möglichkeit, klarer anzugeben, was Ihr Code tatsächlich tut. Im Allgemeinen erstellt das integrierte 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 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 >>>
Denken Sie zur Vereinfachung daran, dass Slice nur eine Form hat:
s[start:end:step]
und so funktioniert es:
s
: ein Objekt, das in Scheiben geschnitten werden kannstart
: Erster Index zum Starten der Iterationend
: letzter Index, HINWEIS: Der end
Index wird nicht in das resultierende Slice aufgenommenstep
: wähle jedes step
Indexelement ausEine weitere Import Sache: alle start
, end
, step
kann verzichtet werden! Und wenn sie nicht angegeben werden, wird ihr Standardwert verwendet werden: 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
), gibt Python ein leeres Slice zurück[]
.
Im obigen Teil werden die Hauptfunktionen für die Funktionsweise von Slice 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.
Das allererste, was Python-Lernende verwirrt, ist, dass ein Index negativ sein kann! Keine Panik: Ein negativer Index bedeutet, rückwärts zu zählen.
Zum Beispiel:
s[-5:] # Start at the 5th index from the end of array,
# thus returning the last 5 elements.
s[:-5] # Start at index 0, and end until the 5th index from end of array,
# thus returning s[0:len(s)-5].
Die Dinge verwirrender zu machen ist, dass step
das auch negativ sein kann!
Ein negativer Schritt bedeutet, dass das Array rückwärts iteriert wird: vom Ende bis zum Start, wobei der Endindex enthalten ist und der Startindex vom Ergebnis ausgeschlossen ist.
HINWEIS : wenn der Schritt negativ ist , ist der Standardwert für start
ist len(s)
(während end
nicht gleich ist 0
, weil s[::-1]
enthält s[0]
). Zum Beispiel:
s[::-1] # Reversed slice
s[len(s)::-1] # The same as above, reversed slice
s[0:len(s):-1] # Empty list
Seien Sie überrascht: Slice löst keinen IndexError aus, wenn der Index außerhalb des Bereichs liegt!
Wenn der Index außerhalb des Bereichs liegt, versucht Python nach besten Kräften, den Index auf 0
oder len(s)
entsprechend der Situation festzulegen. Zum Beispiel:
s[:len(s)+5] # The same as s[:len(s)]
s[-len(s)-5::] # The same as s[0:]
s[len(s)+5::-1] # The same as s[len(s)::-1], and the same as s[::-1]
Lassen Sie uns diese Antwort mit Beispielen beenden und 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, and 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 an IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-15-79ffc22473a3> in <module>()
----> 1 s[11]
IndexError: list index out of range
In den vorherigen Antworten wird nicht auf mehrdimensionales Array-Slicing eingegangen, 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.
list
sondern nur auf array
in Numpy
#!/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. 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.
Mein Gehirn scheint glücklich zu sein, zu akzeptieren, dass es 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]
sie das end
-te Element nicht enthält , weil es in istlst[end:]
.
Beachten Sie, dass dieser Satz für n
alle gilt. Sie können dies beispielsweise überprüfen
lst = range(10)
lst[:-42] + lst[-42:] == lst
kehrt zurück True
.
Meiner Meinung nach werden Sie die Python-String-Slicing-Notation besser verstehen und auswendig lernen, wenn Sie sie folgendermaßen betrachten (lesen Sie weiter).
Lassen Sie uns mit der folgenden Zeichenfolge arbeiten ...
azString = "abcdefghijklmnopqrstuvwxyz"
Für diejenigen, die es nicht wissen, können Sie azString
mithilfe der Notation einen beliebigen Teilstring erstellenazString[x:y]
Aus anderen Programmiersprachen kommend, wird der gesunde Menschenverstand beeinträchtigt. 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 beim ersten Versuch, Strings richtig zu schneiden.
Meine Schlussfolgerung ist, dass x und y als die Grenzindizes angesehen werden sollten, die die Zeichenfolgen umgeben, die wir hinzufügen möchten. Wir sollten den Ausdruck also als azString[index1, index2]
oder noch deutlicher als sehenazString[index_of_first_character, index_after_the_last_character]
.
Hier ist ein Beispiel für eine Visualisierung 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
Sie müssen also nur index1 und index2 auf die Werte setzen, die den gewünschten Teilstring umgeben. Um beispielsweise den Teilstring "cdefgh" abzurufen, können Sie ihn verwendenazString[2:8]
, 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 den Teilstring gewickelt werden ...
ab [ cdefgh ] ij
Dieser Trick funktioniert die ganze Zeit und ist leicht zu merken.
Die meisten der vorherigen Antworten klären Fragen zur Slice-Notation.
Die erweiterte Indizierungssyntax für das Slicing lautet aList[start:stop:step]
: Grundlegende Beispiele sind:
Weitere Schnittbeispiele: 15 Extended Slices
In Python ist die grundlegendste Form zum Schneiden die folgende:
l[start:end]
Wo l
ist eine Sammlung, start
ist ein inklusiver 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 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 three 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, and 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, and 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 völlig neue Sammlung ist. Wenn Sie die Slice-Notation in Zuweisungen verwenden, muss die Länge der Slice-Zuweisungen nicht gleich sein. Die Werte vor und nach dem zugewiesenen Slice werden beibehalten, und die Sammlung wird verkleinert oder vergrößert, um die neuen Werte zu enthalten:
In [16]: l[2:6] = list('abc') # Assigning fewer 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 beim Ausführen einer Zuweisungsoperation weggelassen werden, wird der gesamte Inhalt der Sammlung durch eine Kopie dessen ersetzt, worauf verwiesen wird:
In [20]: l[:] = list('hello...')
In [21]: l
Out[21]: ['h', 'e', 'l', 'l', 'o', '.', '.', '.']
Neben dem einfachen Schneiden ist es auch möglich, die folgende Notation anzuwenden:
l[start:end:step]
Wo l
ist eine Sammlung, start
ist ein inklusiver Index, end
ist ein exklusiver Index und step
ist ein Schritt, der verwendet werden kann, um jedes n-te Element aufzunehmen 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 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
das folgende Beispiel zu verwenden:
In[28]: l[::-2]
Out[28]: [9, 7, 5, 3, 1]
Die Verwendung eines negativen Werts für kann step
jedoch sehr verwirrend werden. Um darüber hinaus zu sein Pythonic , sollten Sie vermeiden , mit start
, end
und step
in einer einzigen Scheibe. Wenn dies erforderlich ist, sollten Sie dies in zwei Aufgaben tun (eine zum Schneiden und die andere zum 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]
Ich möchte eine hinzufügen Hallo, Welt! Beispiel, 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
Die einfachsten Abschnitte dieser Liste sind die 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 Ausschnitt [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 vor dem Element mit dem Index 2
und einem anderen Schnitt vor dem Element mit dem Index 5
. Das Ergebnis ist also ein Schnitt zwischen diesen beiden Schnitten, eine Liste ['T', 'H', 'O']
.
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"
Schnittbeispiel: [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 ist die Beispielverwendung:
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
Wenn Sie der Meinung sind, dass negative Indizes beim Schneiden verwirrend sind, können Sie dies ganz einfach in Betracht ziehen: Ersetzen Sie einfach den negativen Index durch len - index
. Ersetzen Sie beispielsweise -3 durch len(list) - 3
.
Der beste Weg, um zu veranschaulichen, was das Schneiden intern tut, besteht darin, es nur 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 a for-loop with start, end and step
return [list[i] for i in range(start, end, step)]
Die grundlegende Schneidetechnik besteht darin, den Startpunkt, den Haltepunkt und die Schrittgröße zu definieren - auch als Schritt bezeichnet.
Zuerst erstellen wir eine Liste von Werten, die in unserem 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, and step
B = list(range(9))
print("This is List A:", A)
print("This is List B:", B)
Indexieren Sie die Nummer 3 von A und die Nummer 6 von B.
print(A[2])
print(B[6])
Grundlegendes Schneiden
Die erweiterte Indexierungssyntax für das Slicing lautet aList [start: stop: step]. Das Startargument und das Schrittargument sind standardmäßig keine - das einzige erforderliche Argument ist stop. Haben Sie bemerkt, dass dies ähnlich ist, wie der Bereich zum Definieren der Listen A und B verwendet wurde? Dies liegt daran, dass das Slice-Objekt den Satzbereich darstellt, der durch den Bereich (Start, Stopp, Schritt) angegeben wird. Python 3.4-Dokumentation.
Wie Sie sehen können, gibt das Definieren nur von stop ein Element zurück. Da der Start standardmäßig "none" ist, wird nur ein Element abgerufen.
Es ist wichtig zu beachten, dass das erste Element der Index 0 ist, nicht Index 1 ist. Aus diesem Grund verwenden wir für diese Übung zwei Listen. Die Elemente von Liste A werden gemäß der Ordnungsposition nummeriert (das erste Element ist 1, das zweite Element ist 2 usw.), während die Elemente von Liste B die Zahlen sind, die verwendet werden würden, um sie zu indizieren ([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 Stopppositionen definiert werden.
Rufen Sie unter Berücksichtigung des Musters aList [start: stop] die ersten beiden Elemente aus Liste A ab.
Ich denke nicht, dass das Python-Tutorial- Diagramm (in verschiedenen anderen Antworten zitiert) gut ist, da dieser Vorschlag für positive Schritte funktioniert, aber nicht für negative Schritte.
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]
, 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 Indizierung als halboffenes Intervall zu verwenden - rechts offen, wenn positiver Schritt, links offen, wenn negativer Schritt.
Auf diese Weise kann ich mir a[-4:-6:-1]
wie a(-6,-4]
in der Intervallterminologie vorstellen.
+---+---+---+---+---+---+
| 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