Also bin ich gerade auf eine seltsame Python-Funktion gestoßen und wollte etwas Klarheit darüber.
Die folgende Array-Manipulation ist etwas sinnvoll:
p = [1,2,3]
p[3:] = [4]
p = [1,2,3,4]
Ich stelle mir vor, es wird eigentlich nur dieser Wert an das Ende angehängt, richtig?
Warum kann ich das jedoch tun?
p[20:22] = [5,6]
p = [1,2,3,4,5,6]
Und noch mehr:
p[20:100] = [7,8]
p = [1,2,3,4,5,6,7,8]
Dies scheint nur eine falsche Logik zu sein. Es scheint, dass dies einen Fehler auslösen sollte!
Irgendeine Erklärung?
-Ist es nur eine seltsame Sache, die Python macht?
- Gibt es einen Zweck?
- Oder denke ich falsch darüber nach?
python
python-3.x
sequence
slice
range-checking
Akaisteph7
quelle
quelle
if i > sequence.length(): return sequence.slice(0, sequence.length()) else sequence.slice(0, n)
Dies ist genau das gleiche wie bei der Verwendungsequence[:n]
in Python. Es erspart Ihnen eine if-Anweisung und zwei Aufrufe vonlength
.p[20:22]
gilt auch für eine Folge aller Elemente mit Indizes zwischen 20 und 22. Die leere Menge ist eine gültige Menge. Das ist etwas anderes als zu sagen,p[20]
was die Existenz eines Elements mit Index 20 behauptet. Daher spiegelt der Unterschied in der Bereichsprüfung zwischen dem Nachschlagen eines Elements und einem Slice die zwei unterschiedlichen Bedeutungen wider.Antworten:
Ein Teil der Frage zu Indizes außerhalb des Bereichs
Die Slice-Logik schneidet die Indizes automatisch auf die Länge der Sequenz.
Das Ermöglichen, dass sich Slice-Indizes über Endpunkte hinaus erstrecken, wurde der Einfachheit halber durchgeführt. Es wäre mühsam, jeden Ausdruck im Bereich zu überprüfen und dann die Grenzwerte manuell anzupassen, damit Python dies für Sie erledigt.
Stellen Sie sich den Anwendungsfall vor, dass nicht mehr als die ersten 50 Zeichen einer Textnachricht angezeigt werden sollen.
Der einfache Weg (was Python jetzt macht):
preview = msg[:50]
Oder auf die harte Tour (Limit-Checks selbst durchführen):
n = len(msg) preview = msg[:50] if n > 50 else msg
Die manuelle Implementierung dieser Logik zur Anpassung der Endpunkte wäre leicht zu vergessen, wäre leicht zu verwechseln (Aktualisierung der 50 an zwei Stellen), wäre wortreich und langsam. Python verschiebt diese Logik in seine Interna, wo sie kurz, automatisch, schnell und korrekt ist. Dies ist einer der Gründe, warum ich Python liebe :-)
Ein Teil der Frage bezüglich der Nichtübereinstimmung der Zuordnungslänge mit der Eingabelänge
Das OP wollte auch die Gründe für das Zulassen von Zuweisungen kennen, z. B.
p[20:100] = [7,8]
wenn das Zuweisungsziel eine andere Länge (80) als die Länge der Ersatzdaten (2) hat.Es ist am einfachsten, die Motivation durch eine Analogie mit Strings zu erkennen. Betrachten Sie ,
"five little monkeys".replace("little", "humongous")
. Beachten Sie, dass das Ziel "klein" nur sechs Buchstaben und "humongous" neun hat. Wir können dasselbe mit Listen machen:>>> s = list("five little monkeys") >>> i = s.index('l') >>> n = len('little') >>> s[i : i+n ] = list("humongous") >>> ''.join(s) 'five humongous monkeys'
Dies alles hängt von der Bequemlichkeit ab.
Vor der Einführung der Methoden copy () und clear () waren dies beliebte Redewendungen:
s[:] = [] # clear a list t = u[:] # copy a list
Selbst jetzt verwenden wir dies, um Listen beim Filtern zu aktualisieren:
s[:] = [x for x in s if not math.isnan(x)] # filter-out NaN values
Ich hoffe, diese praktischen Beispiele geben einen guten Überblick darüber, warum das Schneiden so funktioniert.
quelle
s[:]
] " - Können Sie erläutern, warum Sies[:] =
dort anstatt nur verwenden würdens =
? Ich habe noch nie jemandens[:] =
im Kontext einer Zeile gesehen, wie Sie sie dort geschrieben haben. Gute Antwort sonst!s
. Verwenden vons =
Neubindungens
, um auf eine neue Liste zu verweisen. Wenn die Liste über mehrere Namen erreichbar ist und Sie möchten, dass die Mutation für alle Namen sichtbar ist, möchten Sie die Slice-Zuweisung. Wenns
eine Neuzuweisung global wäre,s
wäre eineglobal
Deklaration erforderlich , aber die Slice-Zuweisung hätte auch ohne dieglobal
Anweisung einen ähnlichen Effekt .Die Dokumentation hat Ihre Antwort:
Die Dokumentation von
IndexError
bestätigt dieses Verhalten:Im Wesentlichen werden Dinge wie
p[20:100]
auf reduziertp[len(p):len(p]
.p[len(p):len(p]
ist ein leeres Segment am Ende der Liste. Wenn Sie ihm eine Liste zuweisen, wird das Ende der Liste so geändert, dass es diese Liste enthält. Somit funktioniert es wie das Anhängen / Erweitern der ursprünglichen Liste.Dieses Verhalten ist dasselbe wie das, was passiert, wenn Sie einem leeren Slice an einer beliebigen Stelle in der ursprünglichen Liste eine Liste zuweisen . Zum Beispiel:
In [1]: p = [1, 2, 3, 4] In [2]: p[2:2] = [42, 42, 42] In [3]: p Out[3]: [1, 2, 42, 42, 42, 3, 4]
quelle