Frage

Ich versuche, in Scheiben schneiden Funktionalität für eine Klasse zu implementieren ich, damit ich bin das schafft eine Vektordarstellung.

Ich habe diesen Code so weit, das ich glaube, richtig die Scheibe implementieren, aber wenn ich einen Anruf wie v[4] tun, wo v ein Vektor Python einen Fehler zurückgibt über nicht genügend Parameter aufweisen. Also ich versuche, herauszufinden, wie die getitem spezielle Methode in meiner Klasse definieren beide Ebene Indizes und Slicing zu behandeln.

def __getitem__(self, start, stop, step):
    index = start
    if stop == None:
        end = start + 1
    else:
        end = stop
    if step == None:
        stride = 1
    else:
        stride = step
    return self.__data[index:end:stride]
War es hilfreich?

Lösung

Die __getitem__() Methode wird ein slice Objekt erhalten, wenn das Objekt in Scheiben geschnitten wird. Einfach auf der start, stop und step Mitglieder des slice Objekts, um die Komponenten für die Scheibe zu erhalten.

>>> class C(object):
...   def __getitem__(self, val):
...     print val
... 
>>> c = C()
>>> c[3]
3
>>> c[3:4]
slice(3, 4, None)
>>> c[3:4:-2]
slice(3, 4, -2)
>>> c[():1j:'a']
slice((), 1j, 'a')

Andere Tipps

Ich habe eine „synthetische“ Liste (eine, wo die Daten, die größer ist, als Sie im Speicher erstellen möchte) und meine __getitem__ sieht wie folgt aus:

def __getitem__( self, key ) :
    if isinstance( key, slice ) :
        #Get the start, stop, and step from the slice
        return [self[ii] for ii in xrange(*key.indices(len(self)))]
    elif isinstance( key, int ) :
        if key < 0 : #Handle negative indices
            key += len( self )
        if key < 0 or key >= len( self ) :
            raise IndexError, "The index (%d) is out of range."%key
        return self.getData(key) #Get the data from elsewhere
    else:
        raise TypeError, "Invalid argument type."

Die Scheibe nicht den gleichen Typ zurückgeben, das ist ein no-no, aber es funktioniert für mich.

Wie die getitem Klasse zu definieren, beide Indizes Ebene und schneiden zu behandeln?

Slice-Objekte wird automatisch erstellt, wenn Sie einen Doppelpunkt in der Index-Notation - und , die ist, was zu __getitem__ geben wird. Verwenden isinstance zu überprüfen, ob Sie ein Slice-Objekt haben:

from __future__ import print_function

class Sliceable(object):

    def __getitem__(self, given):
        if isinstance(given, slice):
            # do your handling for a slice object:
            print(given.start, given.stop, given.step)
        else:
            # Do your handling for a plain index
            print(given)

Beispiel Nutzung:

>>> sliceme = Sliceable()
>>> sliceme[1]
1
>>> sliceme[2]
2
>>> sliceme[:]
None None None
>>> sliceme[1:]
1 None None
>>> sliceme[1:2]
1 2 None
>>> sliceme[1:2:3]
1 2 3
>>> sliceme[:2:3]
None 2 3
>>> sliceme[::3]
None None 3
>>> sliceme[::]
None None None
>>> sliceme[:]
None None None

Python 2, beachten Sie:

In Python 2 gibt es eine veraltete Methode, dass Sie außer Kraft setzen müssen, wenn einige eingebauten Typen Subklassen.

Von der Datenmodell Dokumentation :

object.__getslice__(self, i, j)

Veraltet seit Version 2.0: Support Segmentobjekte als Parameter an die __getitem__() Methode. (Allerdings eingebauten Typen in CPython derzeit noch __getslice__() implementieren. Deshalb müssen Sie es in abgeleiteten Klassen außer Kraft setzen, wenn Slicing implementieren.)

Dies ist in Python 3 weg.

Der richtige Weg, dies zu tun ist, __getitem__ nimmt einen Parameter zu haben, die entweder eine Zahl sein können, oder ein Segmentobjekt.

Siehe auch:

http://docs.python.org/library/functions.html#slice

http://docs.python.org/reference/datamodel.html#object.__getitem__

Um Aaron Antwort, für Dinge wie numpy zu erweitern, können Sie mehrdimensionale Slicing tun, indem Sie überprüfen, ob given ein tuple ist:

class Sliceable(object):
    def __getitem__(self, given):
        if isinstance(given, slice):
            # do your handling for a slice object:
            print("slice", given.start, given.stop, given.step)
        elif isinstance(given, tuple):
            print("multidim", given)
        else:
            # Do your handling for a plain index
            print("plain", given)

sliceme = Sliceable()
sliceme[1]
sliceme[::]
sliceme[1:, ::2]

`` `

Ausgabe:

('plain', 1)
('slice', None, None, None)
('multidim', (slice(1, None, None), slice(None, None, 2)))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top