Die Python-Funktion slice(start, stop, step) erzeugt ein Slice-Objekt — die objekt-orientierte Form des Slicing-Ausdrucks seq[a:b:c]. Slice-Objekte lassen sich in Variablen speichern, mehrfach verwenden und an Funktionen übergeben — etwas, das die Bracket-Notation nicht erlaubt. Außerdem ist slice das, was Python intern in __getitem__()-Aufrufen liefert, wenn man seq[1:3] schreibt.
Einleitung
In Python ist seq[1:5:2] syntaktischer Zucker für seq.__getitem__(slice(1, 5, 2)). Der Slice-Konstruktor wird normalerweise nicht direkt benutzt — aber er ist nützlich in drei Situationen:
- Wiederverwendbare Slices:
headers = slice(0, 10)— und danndata[headers]an mehreren Stellen. - Funktional: An Funktionen oder Map-Strukturen weiterreichen.
- Custom-
__getitem__: Eigene Klassen, die Slicing implementieren, bekommen einslice-Objekt übergeben.
Die Methode slice.indices(length) gibt die effektiven (start, stop, step) für eine konkrete Sequenz-Länge zurück — sehr praktisch beim Implementieren eigener Slice-Logik.
Syntax
slice(stop)
slice(start, stop)
slice(start, stop, step)start (Optional) Start-Index. Default: None (= 0 bei Auswertung).
stop Stopp-Index (exklusiv).
step (Optional) Schrittweite. Default: None (= 1).
Rückgabewert
Ein slice-Objekt mit den Attributen start, stop, step.
Beispiele
Slice-Objekt direkt verwenden
Ein gespeicherter Slice ist genauso anwendbar wie die Bracket-Notation, aber wiederverwendbar:
s = slice(1, 5)
data = [10, 20, 30, 40, 50, 60]
print(data[s])
print(data[1:5]) # äquivalent[20, 30, 40, 50]
[20, 30, 40, 50]Wiederverwendbare Slices als Konstanten
Wenn dieselbe Sub-Range mehrfach gebraucht wird, lohnt sich ein Slice-Konstanten-Block — kein magic number more:
# Tabellen-Layout: Spalten 0-3 = Header, 4-9 = Daten, ab 10 = Footer
HEADER = slice(0, 4)
DATA = slice(4, 10)
FOOTER = slice(10, None)
row = list("abcdefghijklmn")
print(row[HEADER])
print(row[DATA])
print(row[FOOTER])['a', 'b', 'c', 'd']
['e', 'f', 'g', 'h', 'i', 'j']
['k', 'l', 'm', 'n']slice.indices() für eigene Klassen
indices(length) normalisiert einen Slice gegen eine konkrete Länge und löst negative oder fehlende Werte auf:
s = slice(None, None, 2)
print(s.indices(10)) # (start, stop, step) für Länge 10
s2 = slice(-3, None)
print(s2.indices(10))(0, 10, 2)
(7, 10, 1)Custom-Klasse mit Slicing
Eigene Sequenz-Typen bekommen automatisch ein slice-Objekt im __getitem__, sobald seq[a:b]-Syntax benutzt wird:
class Range:
def __init__(self, n):
self._values = list(range(n))
def __getitem__(self, key):
if isinstance(key, slice):
start, stop, step = key.indices(len(self._values))
return [self._values[i] for i in range(start, stop, step)]
return self._values[key]
r = Range(10)
print(r[2:8:2])[2, 4, 6]Praktische Beispiele
Slice an Funktion übergeben
Funktionen, die einen "Bereich" als Argument nehmen, können slice-Objekte direkt akzeptieren — ausdrucksstärker als zwei Indizes:
def average(values, where):
chunk = values[where]
return sum(chunk) / len(chunk)
prices = [10, 12, 11, 13, 15, 14, 16, 17]
last_three = slice(-3, None)
print(average(prices, last_three))15.666666666666666Negative Slices via Konstanten lesbarer machen
Statt magischer [-3:] lässt sich der Bereich benennen — das macht Reviews leichter:
LAST_THREE = slice(-3, None)
FIRST_TWO = slice(0, 2)
EVERY_OTHER = slice(None, None, 2)
items = list("abcdefghi")
print(items[LAST_THREE])
print(items[FIRST_TWO])
print(items[EVERY_OTHER])['g', 'h', 'i']
['a', 'b']
['a', 'c', 'e', 'g', 'i']Praktische Hinweise
- Bracket-Syntax bleibt der Standard —
slice()nur, wenn der Bereich gespeichert/übergeben werden soll oder bei Custom-__getitem__. slice.indices(length)ist Pflichtwerkzeug, wenn eigene Klassen Slicing implementieren.sliceist immutable und hashable — kann als Dict-Key oder Set-Element genutzt werden.numpy.s_[...]ist eine kompakte Alternative im NumPy-Ökosystem (s_[1:5, ::2]baut Tupel von Slices).- Verwandte Konzepte:
__getitem__,__setitem__,range().