Ich wurde auf die Referenzimplementierung (Huttip zum anonymen Wohltäter) hingewiesen und festgestellt, dass es ziemlich einfach ist, das Verhalten von dort zu verstehen. Um vollständig zu sein, IMHO ist dieses Verhalten nicht intuitiv, aber es ist dennoch gut definiert und entspricht der Referenzimplementierung.
Zwei CPython-Dateien sind relevant, nämlich diejenigen, die list_subscript und PySlice_AdjustIndices beschreiben. Beim Abrufen eines Slice aus einer Liste wie in diesem Fall wird list_subskript aufgerufen. Es ruft PySlice_GetIndicesEx, die ihrerseits ruft PySlice_AdjustIndices. Jetzt PySlice_AdjustIndices enthält einfache if/then-Anweisungen, die die Indizes anpassen. Am Ende gibt es die Länge der Scheibe zurück. Für unseren Fall sind die Linien
if (*stop < 0) {
*stop += length;
if (*stop < 0) {
*stop = (step < 0) ? -1 : 0;
}
}
von besonderer Relevanz. Nach der Anpassung wird x[0:-len(x)-1:-1]
zu x[0:-1:-1]
und die Länge 1 wird zurückgegeben. Wenn jedoch x[0:-1:-1]
zur Anpassung übergeben wird, wird es x[0:len(x)-1:-1]
der Länge 0. Mit anderen Worten, f(x) != f(f(x))
in diesem Fall.
Es ist amüsant zu beachten, dass der folgende Kommentar in PySlice_AdjustIndices gibt es:
/* this is harder to get right than you might think */
Schließlich ist zu beachten, dass die Übergabe der Situation in Frage nicht in dem Python docs beschrieben.
Danke für die Antwort, aber ich verstehe es immer noch nicht. Sie schreiben, dass -len (x) -1 in -1 aufgelöst wird. Könntest du bitte erläutern, wie es sich auf -1 auflöst und warum, denn für mich ist -len (x) -1 gleich -7. Bezieht es sich auf die Tatsache, dass x [0] == x [-len (x)]? – ffc
Ja. Jede negative Zahl "-i", die als ein Index- oder Slice-Parameter in einer Sequenz "seq" verwendet wird, wird in den tatsächlichen Index "len (seq) - i" aufgelöst. Für eine "liste" der Länge "6" ist also "l [0: -7: -1]" eine Scheibe von "0" bis "-1" ("6 - 7") in Rückwärtsschritten. Für jede Rückwärtsscheibe, die das erste Element enthält (Index '0'), müssen Sie 'end <-len (seq)' wählen oder es leer lassen: 'seq [start :: - 1]'! – schwobaseggl