[Python] Warum Slices keine Indexfehler verursachen

Einführung

Es ist eine bekannte Geschichte (ich vergesse oft), dass unabhängig davon, wie groß oder klein eine Zahl in einem Python-Slice angegeben ist, kein Indexfehler auftritt, aber der Grund ist "** Es behandelt es intern gut. ** ”Ich dachte, ich könnte keinen Artikel auf Japanisch finden, der das oben Genannte erklärt, und beschloss, ihn als Lückenindustrie zu schreiben.

In diesem Artikel werde ich das Thema des Themas aus zwei Perspektiven erläutern: ** Idee ** und ** Umsetzung . Ich hoffe, die Krankheit von Leuten loszuwerden, die Python noch nicht kennen und das Gefühl haben, dass " Indexfehler beim Extrahieren eines bestimmten Elements May als Slice bezeichnet wird, aber nicht als Slice **". Ich werde.

Da der Autor selbst unerfahren ist, würde ich es auch begrüßen, wenn Sie auf Ungenauigkeiten in den Ausdrücken für ein späteres Studium hinweisen könnten.

Was macht eine Scheibe (überhaupt)?

Dieser Abschnitt entspricht dem Ideenteil des Schneidens. Selbst im offiziellen Dokument ist "Was ist ein Slice?" Nicht einfach und klar geschrieben (sieht so aus), aber es ist frustrierend, aber vorerst gibt es die folgende Erklärung.

--Hinweis zu s [i: j]

Eine Schicht von> s von i bis j ist als eine Folge von Elementen mit einem Index k definiert, so dass i <= k <j ist.

--Hinweis zu s [i: j: k]

Das> s "Slice von i nach j mit den Schritten k" besteht aus Elementen mit einem Index x = i + n * k (wobei n eine beliebige ganze Zahl ist, die 0 <= n <(ji) / k erfüllt). Als Sequenz definiert.

Integrierte Dokumentation zu Python 3.8.5

Sie können es verstehen, wenn Sie es richtig lesen, aber es fühlt sich ein wenig nervig an.

Wenn Sie nur die Teile extrahieren, die Sie jetzt benötigen, bedeutet das Schneiden, dass "eine neue ** Sequenz ** aus ** Elementen ** erstellt wird, die dem angegebenen Index ** aus der ursprünglichen Sequenz entsprechen"?

(Eine Sequenz ist ein Datentyp wie Liste, Taple, Bereich, Zeichenfolge, Bytezeichenfolge usw.)

Hier ist ein Zitat von Stack Overflow, warum dies wichtig ist.

Indexing returns a single item, but slicing returns a subsequence of items. So when you try to index a nonexistent value, there's nothing to return. But when you slice a sequence outside of bounds, you can still return an empty sequence.

https://stackoverflow.com/a/9490148

Mit anderen Worten

  1. Die Elementextraktion gibt ein einzelnes Element zurück, aber Slices geben eine Sequenz zurück.
  2. Wenn Sie einen Index angeben, der in der Elementextraktion nicht vorhanden ist, gibt es nichts zurückzugeben. Wenn es sich jedoch um eine Sequenz handelt, können Sie eine leere Sequenz zurückgeben.

Ich sage das. Ich habe oben 1 erwähnt, daher denke ich nicht, dass es notwendig ist, es zu erklären, aber was ist mit 2?

Kurz gesagt, [0,1,2] [3] ist ** ein Fehler, da es keinen Rückgabewert ** gibt, aber [0,1,2] [3:] ist ein Element, das Index 3 oder höher entspricht. Wenn keine ** leere Liste vorhanden ist, kann [[] `als Rückgabewert zurückgegeben werden, sodass kein Fehler ** erforderlich ist.

Das heißt, die Antoinette-Leute (einschließlich des Autors), die dies lesen, sagten: "** Wenn Sie einen Rückgabewert haben müssen, können Sie None mit" [0,1,2] [3] "zurückgeben. Sie könnten denken, "Es ist nicht gut **".

In diesem Fall ist es jedoch möglich zu bestimmen, ob ** [0,1,2] [3] None zurückgibt oder [0,1,2, None] [3] None zurückgibt ** Ich brauche immer noch einen Indexfehler, weil er schwieriger wird (und ihn freundlicherweise in der Fortsetzung des vorherigen Zitats ergänzt).

Die Erklärung mag etwas redundant gewesen sein, aber die Schlussfolgerung war, dass der Fehler "** Slice kann eine leere Sequenz zurückgeben, auch wenn kein entsprechendes Element ** vorhanden ist" nicht auftritt.

(Jabashi: Ich möchte Begriffe wie "Teilmenge / Teilzeichenfolge" und "leere Menge" verwenden, aber wenn ich "Menge" sage, ignoriere ich das Element des Sequenztyps "Reihenfolge". Schließlich bleibt nichts anderes übrig, als es wie das offizielle Dokument zu erklären.)

Die wahre Identität des "guten Gefühls"

Dieser Abschnitt entspricht dem Implementierungsteil des Slice.

Wie gehen Sie mit Operationen wie "[P, y, t, h, o, n] [100: 200]" auf "gute Weise" um? Die Antwort ist eine Fortsetzung des Zitats aus dem offiziellen Dokument im vorherigen Abschnitt. Es ist im Teil versteckt.

--Hinweis zu s [i: j]

Wenn> i oder j größer als len (s) ist, verwenden Sie len (s). Wenn i weggelassen wird oder Keine, verwenden Sie 0. Wenn j weggelassen wird oder Keine, verwenden Sie len (s). Wenn i größer oder gleich j ist, ist das Slice eine leere Sequenz.

Mit anderen Worten, in "[P, y, t, h, o, n] [100: 200]" wird "len (s)" verwendet, weil sowohl "i" als auch "j" größer als "len (s)" sind. Dann gilt "i (= len (s))> = j (= len (s))", so dass beurteilt wird, dass eine leere Sequenz zurückgegeben wird.

[Slices werden auch intern indiziert](https://qiita.com/tanuk1647/items/276d2be36f5abb8ea52e#How Slices werden in Indizes konvertiert), daher sind sie größer als "len (s)" Die Zahlen werden im Voraus umgerechnet. Wenn Sie "Schritt" angeben, wird im Grunde die gleiche Verarbeitung ausgeführt.

Abschließend werde ich Ihnen einen Hinweis geben, wie die Verarbeitung hier in CPython implementiert ist. Ich bin auch nicht stark in C, daher denke ich, dass Sie es in dem Maße betrachten sollten, dass "Ah, es ist definitiv so geschrieben" (auch im Quellcode / * ist es schwieriger, es richtig zu machen, als Sie vielleicht könnten). Es heißt denken * / ).

(In diesem Abschnitt haben wir den Fall erklärt, in dem "Schritt" nicht verwendet wird, aber im Anführungszeichen ist es der Prozess, in dem "Schritt" verwendet wird. Ich weiß es nicht.)

sliceobject.c


defstop = *step < 0 ? -1 : length;
...
if (r->stop == Py_None) {
    *stop = defstop;
}
...
if ((*step < 0 && *stop >= *start)
    || (*step > 0 && *start >= *stop)) {
    *slicelength = 0;

cpython: 3a1db0d2747e Objects/sliceobject.c

Fazit

Das Schneiden ist bequem.

Danke, dass du bis zum Ende zugesehen hast.

Referenzseite

Integrierte Dokumentation zu Python 3.8.5 [Python] Zusammenfassung der Schneidevorgänge --Qiita python - Why does substring slicing with index out of range work? - Stack Overflow string - Why python's list slicing doesn't produce index out of bound error? - Stack Overflow

Recommended Posts

[Python] Warum Slices keine Indexfehler verursachen
Python nicht implementiert Fehler
Schlüsseleingabe, die nicht auf Schlüsseleingabe in Python wartet
BigQuery - Wenn Sie einen Grund erhalten: responseTooLarge-Fehler in Python
Messen Sie den BMI-Index in Python.
Hinweis zur Unterstützung von Python-Fehlern: "... unterstützt kein Argument 0 vom Typ float ..."
Python-Version wechselt nicht
Python> enthält die Buchstaben mm> nicht, wenn "mm" nicht im Text enthalten ist: / print "mm nicht enthalten"
[Python] Namensfehler: name'urlparse 'ist nicht definiert
Pfadproblem tritt unter Debian-Linux nicht auf
[Illegale Hardware-Anweisung Python] Fehler in PyMC3
Das Autopep8-Format [VScode] funktioniert nicht. [Python]
Virtualenv funktioniert nicht unter Python 3.5 (Windows)
Python / Wörterbuch> setdefault ()> Hinzufügen, wenn nicht im Wörterbuch
Python> Python enthält nicht den letzten Offset
Tensorflow tritt nicht in Windows + Anaconda ein.
Tkinter konnte nicht in Python importiert werden
In Ruby ersetzt inspect nicht to_s
Importfehler: Kein Modul mit dem Namen 'xxxxx' in Python3
Warum kann ich matplotlib nicht mit Python installieren? !!
Was ist der Grund, warum der Mensch keine grundlegenden Befehle auf Japanisch anzeigt?
Patch, wenn die Volltextsuche in der lokalen GAE / Python-Umgebung nicht funktioniert