2011-07-03 9 views
21

me gustaría escribir una clase de lista personalizada en Python (llamémoslo MyCollection) donde eventualmente puede llamar:¿Cómo crearía una clase de lista personalizada en python?

for x in myCollectionInstance: 
    #do something here 

¿Cómo voy a ir haciendo eso? ¿Hay alguna clase que extender, o hay alguna función que debo anular para poder hacerlo?

+0

¿Podría aclarar mejor sus requisitos? Si subclases cualquier clase iterable (list, dict, etc ...) debería funcionar sin problemas. Pero tal vez me estoy perdiendo algo? – mac

+0

@mac: si subclasé una clase iterable, también me gustaría una forma de poder acceder al objeto de la lista subyacente para poder proporcionar funciones adicionales que actúen sobre él. No quiero un par clave-valor (dict), por lo que algo que emula una colección indexada (lista) sería suficiente. –

Respuesta

25

Tu puede subclase list si su colección, básicamente, se comporta como una lista:

class MyCollection(list): 
    def __init__(self, *args, **kwargs): 
     super(MyCollection, self).__init__(args[0]) 

Sin embargo, si su deseo principal es que su colección es compatible con el protocolo de iteración, sólo hay que proporcionar una __iter__ método:

class MyCollection(object): 
    def __init__(self): 
     self._data = [4, 8, 15, 16, 23, 42] 

    def __iter__(self): 
     for elem in self._data: 
      yield elem 

Esto le permite iterar sobre cualquier instancia de MyCollection.

+1

Creo que la firma de su supermétodo es incorrecta (solo el 99% de seguridad, pero no 'lista()' acepta solo un iterable como argumento? Además, ¿hay alguna razón especial para los dos puntos finales en la llamada 'super' ? – mac

+1

Sí, tienes razón, he editado para codificar. Gracias por la pista – jena

3

Usted podría extender la clase list: el uso

class MyList(list): 

    def __init__(self, *args): 
     super(MyList, self).__init__(args[0]) 
     # Do something with the other args (and potentially kwars) 

Ejemplo:

a = MyList((1,2,3), 35, 22) 
print(a) 
for x in a: 
    print(x) 

Resultados previstos:

[1, 2, 3] 
1 
2 
3 
10

me gusta subclase MutableSequence, como recommended by Alex Martelli. Esto funciona bien para mí, particularmente cuando necesito agregar métodos personalizados en la parte superior de la lista que estoy construyendo.

from collections import MutableSequence 

class MyList(MutableSequence): 
    """A container for manipulating lists of hosts""" 
    def __init__(self, data=None): 
     """Initialize the class""" 
     super(MyList, self).__init__() 
     if (data is not None): 
      self._list = list(data) 
     else: 
      self._list = list() 

    def __repr__(self): 
     return "<{0} {1}>".format(self.__class__.__name__, self._list) 

    def __len__(self): 
     """List length""" 
     return len(self._list) 

    def __getitem__(self, ii): 
     """Get a list item""" 
     return self._list[ii] 

    def __delitem__(self, ii): 
     """Delete an item""" 
     del self._list[ii] 

    def __setitem__(self, ii, val): 
     # optional: self._acl_check(val) 
     self._list[ii] = val 

    def __str__(self): 
     return str(self._list) 

    def insert(self, ii, val): 
     # optional: self._acl_check(val) 
     self._list.insert(ii, val) 

    def append(self, val): 
     self.insert(len(self._list), val) 

if __name__=='__main__': 
    foo = MyList([1,2,3,4,5]) 
    foo.append(6) 
    print foo # <MyList [1, 2, 3, 4, 5, 6]> 
+4

'if not (data is None):' así no escribes tu código python, hasta que seas un Grand Jedi Master. 'If los datos no son None' - esto se ve bien. – byashimov

Cuestiones relacionadas