5 Stimmen

Warum fügt Python None in Slice-Schritte ein?

Dies lässt sich am besten an einem Beispiel verdeutlichen (alle Beispiele gehen von ast importiert wird; beachten Sie, dass ich Python 2.7.1 verwende):

# Outputs: Slice(lower=Num(n=1), upper=Num(n=10), step=None)
ast.dump(ast.parse("l[1:10]").body[0].value.slice)

# Outputs: Slice(lower=Num(n=1), upper=Num(n=10), step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[1:10:]").body[0].value.slice)

# Outputs: Slice(lower=Num(n=1), upper=None, step=None)
ast.dump(ast.parse("l[1:]").body[0].value.slice)

# Outputs: Slice(lower=None, upper=None, step=None)
ast.dump(ast.parse("l[:]").body[0].value.slice)

Wie wir also sehen können, l[1:10] ergibt einen AST-Knoten, dessen Slice zwei Kinder hat - lower y upper beide auf numerische Literale gesetzt - und eine leere dritte step Kind. Aber [1:10:] die wir als identisch ansehen würden, setzt seine Slice's step Kind zu sein None wörtlicher Ausdruck ( Name(id='None', ctx=Load()) ).

Okay, dachte ich. Vielleicht behandelt Python l[1:10:] y l[1:10] als völlig verschiedene Arten von Ausdrücken. Die Python-Ausdruck-Referenz ( enlace ) schien darauf hinzudeuten; l[1:10] ist ein einfaches Slicing, aber l[1:10:] ist ein erweitertes Slicing (mit nur einem Slice Item).

Aber auch im Zusammenhang mit dem erweiterten Slicing wird das Schrittargument besonders behandelt. Wenn wir versuchen, die obere oder untere Grenze in einem erweiterten Slicing mit einem Slice-Element zu ignorieren, erhalten wir nur leere Kinder:

# Outputs: Slice(lower=Num(n=1), upper=None, step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[1::]").body[0].value.slice)

# Outputs: Slice(lower=None, upper=Num(n=10), step=Name(id='None', ctx=Load()))
ast.dump(ast.parse("l[:10:]").body[0].value.slice)

Bei näherer Betrachtung stellt sich außerdem heraus, dass die AST diese Schnitte nicht einmal als erweiterte Schnitte behandelt. Hier sehen Sie, wie erweiterte Slicings tatsächlich aussehen:

# Outputs: ExtSlice(dims=[Slice(lower=None, upper=None, step=Name(id='None', ctx=Load())), Slice(lower=None, upper=None, step=Name(id='None', ctx=Load()))])
ast.dump(ast.parse("l[::, ::]").body[0].value.slice)

Meine Schlussfolgerung lautet also: Die AST behandelt immer die step Parameter aus irgendeinem Grund besonders und, unabhängig davon, die Slice AST-Knoten stellt eine lange Scheibe dar (ich nehme an, damit es nicht zwei verschiedene Basis Slice Klassen- ShortSlice y LongSlice -(obwohl ich denke, dass dies vorzuziehen wäre) und so kann eine erweiterte Scheibe mit einem einzigen Element als normale Scheibe dargestellt werden. Slice Knoten und wird aus irgendeinem Grund so gemacht. Es scheint mir einfach falsch zu sein, zu erlauben None Parameter als Standardwerte zu interpretieren, aber ich verstehe, dass dies eine bewusste Designentscheidung war; die None wörtliche Einfügung und Behandlung langer Scheiben als Slice Die Knotenpunkte wirken wie Unfälle (oder Artefakte alter Designs).

Hat sonst noch jemand eine fundiertere Erklärung?

3voto

Alan Franzoni Punkte 2921

Ohne eine solche Behandlung in der erweiterten Slice-Notation wäre es nicht möglich, zu unterscheiden zwischen l[1:] y l[1::] und man konnte nicht verschiedene spezielle Methoden aufrufen - __getslice__ kann für ein normales Slice aufgerufen werden, aber __getitem__ muss für ein erweitertes Slice aufgerufen werden.

Es handelt sich also hauptsächlich um eine Rückwärtskompatibilitätssache für Python 2.x, die in Python 3.x verschwunden ist:

Python 3.2 (r32:88445, Mar 25 2011, 19:28:28) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ast
>>> ast.dump(ast.parse("l[1:]").body[0].value.slice)
'Slice(lower=Num(n=1), upper=None, step=None)'
>>> ast.dump(ast.parse("l[1::]").body[0].value.slice)
'Slice(lower=Num(n=1), upper=None, step=None)'
>>> 

Véase python2.7-Quelltext für ast.c y Datenmodellbeschreibung für weitere Informationen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X