Question

Je suis en train de mettre en œuvre la fonctionnalité de tranche pour une classe que je fais qui crée une représentation vectorielle.

Je le code à ce jour, qui, je crois bien mettre en œuvre la tranche, mais chaque fois que je fais un appel comme v[4] où v est un python vecteur renvoie une erreur de ne pas avoir assez de paramètres. J'essaie donc de comprendre comment définir la méthode getitem spéciale dans ma classe pour gérer les deux indices simples et trancher.

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]
Était-ce utile?

La solution

La méthode __getitem__() recevra un objet slice lorsque l'objet est coupé en tranches. Il suffit de regarder le start, stop, et les membres de step de l'objet slice afin d'obtenir les composants pour la tranche.

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

Autres conseils

J'ai une liste « synthétique » (celui où les données est plus grand que vous voulez créer dans la mémoire) et mes regards __getitem__ comme ceci:

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 tranche ne retourne pas le même type, ce qui est un non-non, mais ça marche pour moi.

  

Comment définir la classe getitem pour gérer les index simples et découpage en tranches?

objets Slice créée automatiquement lorsque vous utilisez deux points dans la notation de l'indice - et que est ce qui est passé à __getitem__. Utilisez isinstance pour vérifier si vous avez un objet de tranche:

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)

Exemple d'utilisation:

>>> 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, il faut savoir:

En Python 2, il y a une méthode désapprouvée que vous devrez peut-être remplacer lorsque certains types de sous-classement BUILTIN.

De la datamodel documentation :

  

object.__getslice__(self, i, j)

     

Obsolète depuis la version 2.0: objets tranche de support en tant que paramètres à la méthode __getitem__(). (Cependant, les types intégrés dans CPython mettent actuellement en œuvre encore __getslice__(). Par conséquent, vous devez le remplacer dans les classes dérivées lors de la mise en œuvre découpage en tranches.)

est parti en Python 3.

La bonne façon de le faire est d'avoir __getitem__ prendre un paramètre, qui peut être un nombre ou un objet de tranche.

Voir:

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

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

Pour prolonger la réponse d'Aaron, pour des choses comme numpy, vous pouvez le faire trancher multi-dimensionnelle en vérifiant si given est 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]

`` `

Sortie:

('plain', 1)
('slice', None, None, None)
('multidim', (slice(1, None, None), slice(None, None, 2)))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top