2017-01-21 3 views
1

Ich versuche das folgende Verhalten zu verstehen und würde jegliche Hinweise (insbesondere zu offiziellen Dokumenten) oder Kommentare begrüßen.Negative Schritte beim Auflisten von Listen verstehen

Lassen Sie uns eine Liste betrachten:

>>> x = [1,2,3,4,5,6] 

Dies als

>>> x[-1:-4:-1] 
[6, 5, 4] 

erwartet funktioniert, aber ich bin der überrascht folgende leer ist:

>>> x[0:-4:-1] 
[] 

Ich bin daher überrascht die folgende ist nicht leer

>>> x[0:-len(x)-1:-1] 
> [1] 

zumal

>>> x[0:-len(x):-1] 
[] 

und auch, dass

>>> x[0:-len(x)-1] 
[] 

ist leer.

Antwort

2

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.

4

Die Tatsache, dass

> x[-1:-4:-1] 
[6, 5, 4] 
> x[0:-4:-1] 
[] 

sollten Sie nicht überraschen! Es ist ziemlich offensichtlich, dass Sie eine Liste vom letzten bis zum viertletzten Element in Rückwärtsschritten aufteilen können, aber nicht vom ersten Element.

In

x[0:i:-1] 

die i muss < -len(x) sein, um einen Index < 0 für das Ergebnis zu lösen, um ein Element zu enthalten. Die Syntax der Scheibe einfach ist auf diese Weise:

x[start:end:step] 

Mittel, beginnt die Scheibe an start (hier: 0) und endet vor end (oder von jedem negativen end referenzierten Index). -len(x) löst sich auf 0, ergo eine Scheibe ab 0 und endet bei 0 ist von Länge 0, enthält keine Elemente. -len(x)-1 wird jedoch zu dem tatsächlichen -1 aufgelöst, was zu einem Stück der Länge 1 ab 0 führt.

Weggehen end leer in einer Rückwärts Scheibe mehr intuitiv verstanden:

> l[2::-1] 
[3, 2, 1] 
> l[0::-1] 
[1] 
+0

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

+0

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

-1
x[0:-4:-1] 

geht von 0 bis 2 mit -1 Schritten?

Verwandte Themen