Fragen zu slice() und islice()...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

die Python-Dokumentation schreibt zu slice():
Slice objects have read-only data attributes start, stop and step which merely return the argument values (or their default). They have no other explicit functionality; however they are used by Numerical Python and other third party extensions.
  • 1. Wenn dem so ist, weshalb ist slice() dann eine built-in Funktion? Und warum islice() nicht, wird es doch ganz konkret bei Generatoren benötigt, bei denen ein Zugriff mit [::] naturgemäß nicht funktioniert?
    2. Hätte mir jemand mal ein Beispiel, wo ich mit [::] nicht weiterkomme und slice() brauche?
    3. Ist es richtig, dass islice() i. d. R. nur bei Generatoren zum Einsatz kommt?
Gruß
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: 1. Für den Aufruf brauchst Du `slice`-Objekte nicht, aber für die Implementierung von `__getitem__()`. Da wird nämlich ein `slice` übergeben, wenn jemand die Methode über die "Slice-Syntax" aufruft. Die `__getslice__()`-Methode ist ja deprecated, also braucht man `slice` um in der `__getitem__()` (und `__setitem__()`/`__delitem__()`) zwischen einem einfachen Index und einem "Slice"-Aufruf unterscheiden zu können, beziehungsweise dann auch entsprechend an die Werte des `slice` zu kommen, sofern man ihn nicht einfach nur weiter reicht.

`slice` betrifft also direkt die Implementierung von wichtigen Objekt-Methoden. `islice()` dagegen ist einfach nur eine Funktion. Die Sprache ist sehr lange ohne ausgekommen. Und man möchte ja nicht alles was irgendwie nützlich ist, in die "built-ins" stecken. Dann kann man ja gleich PHP verwenden. ;-)

2. Wie gesagt, man braucht `slice` wenn man `__(get|set|del)item__()` implementiert und da eben auch `slice`-Objekte bekommen kann.

3. `islice()` funktioniert mit allen "iterables", also auch mit Sequenzen wie zum Beispiel Listen oder Zeichenketten.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

BlackJack hat geschrieben:`islice()` funktioniert mit allen "iterables", ...
Schon klar, nur macht der praktische Einsatz außer bei Generatoren auch Sinn? Wo liegt der Unterschied zwischen

Code: Alles auswählen

'ABC'[1:2]
oder

Code: Alles auswählen

islice('ABC',1,2)
abgesehen vom Rückgabetype, was ja bei einer Verwendung innerhalb einer for .. in .. -Schleife keinen Unterschied machen würde?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Kann man also sagen, dass slice() die zugrunde liegende Funktion einer seq[::]-Anweisung ist?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Beim "slice"n *muss* man eine Sequenz verwenden, welche die "Slice"-Notation versteht und es wird (in der Regel) ein neues unabhängiges Objekt erzeugt, das alle betroffenen Elemente enthält. Bei `islice()` geht jedes "iterable". Das ist halt allgemeiner und kann mit mehr Objekten benutzt werden.

Ich versuche so allgemein wie möglich und so "lazy" wie möglich zu programmieren, also halt `islice()` zu verwenden, wenn die Möglichkeit besteht. Gegenanzeichen sind Fälle wo man die Länge wissen muss, also zum Beispiel für negative Slice-Argumente, oder wenn das erzeugen eines Generators im Verhältnis zu viel Aufwand gegenüber einer Kopie bedeutet. Bei ``'ABC'[1:2]`` würde ich also keinen Iterator bemühen. Aber mal als fiktives Beispiel: Wenn ich jedes zweite Zeichen/Byte eines CD-Images verarbeiten möchte, dann würde ich auch bei den heutigen Arbeitsspeichergrössen vielleicht doch eher einen Iterator statt einer Kopie der Hälfte der Daten verwenden.

Ist natürlich ein blödes Beispiel, denn da wäre vielleicht auch eher ein `numpy`-Array angesagt und dort dann "slicing" weil das *keine* Kopie erzeugt, sondern man einfach ein Objekt bekommt, welches einen anderen "view" auf die Daten darstellt. Zuweisungen an einen Index verändern da auch das zugrundeliegende Array von dem man "geslicet" hat.

`slice`-Objekte spielen bei der Implementierung von ``[::]``-Verhalten eine wichtige Rolle, ja.
Antworten