Domanda

Sto cercando di implementare la funzionalità fetta per una classe che sto facendo che crea una rappresentazione vettoriale.

Ho questo codice finora, che credo applicare correttamente la fetta, ma ogni volta che faccio una chiamata come v[4] dove v è un vettore di pitone restituisce un errore di non avere abbastanza parametri. Così sto cercando di capire come definire il metodo speciale getitem nella mia classe per gestire sia gli indici di pianura e affettare.

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]
È stato utile?

Soluzione

Il metodo __getitem__() riceverà un oggetto slice quando l'oggetto viene affettato. Basta guardare il start, stop, e membri step dell'oggetto slice al fine di ottenere i componenti della porzione.

>>> 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')

Altri suggerimenti

Ho una lista "sintetico" (quella in cui il dato è più grande di quanto si vorrebbe creare in memoria) e il mio aspetto __getitem__ come questo:

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."

La fetta non restituisce lo stesso tipo, che è un no-no, ma funziona per me.

  

Come definire la classe getitem per gestire sia gli indici semplici e affettare?

Slice oggetti viene creato automaticamente quando si utilizza un colon nella notazione pedice - e che è ciò che è passato a __getitem__. Utilizzare isinstance per verificare se si dispone di un oggetto porzione:

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)

Esempio di utilizzo:

>>> 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, essere consapevoli:

In Python 2, c'è un metodo deprecato che potrebbe essere necessario eseguire l'override quando sottoclasse alcuni tipi built-in.

datamodel documentazione :

  

object.__getslice__(self, i, j)

     

Sconsigliata a partire da versione 2.0: fetta supporta gli oggetti come parametri al metodo __getitem__(). (Tuttavia, tipi built-in in CPython attualmente ancora implementare __getslice__(). Pertanto, è necessario eseguire l'override in classi derivate in sede di attuazione affettare.)

Questo è andato in Python 3.

Il modo corretto per farlo è avere __getitem__ prendere un parametro, che può essere un numero o un oggetto porzione.

Si veda:

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

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

Per estendere la risposta di Aaron, per le cose come numpy, si può fare per affettare multi-dimensionale controllando per vedere se given è un tuple:

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]

`` `

Output:

('plain', 1)
('slice', None, None, None)
('multidim', (slice(1, None, None), slice(None, None, 2)))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top