2010-10-15 12 views
17

Hace poco estuve repasando un problema de codificación que tenía y alguien que miraba el código decía que la lista de subclases era mala (mi problema no estaba relacionado con esa clase). Dijo que no deberías hacerlo y que venía con un montón de malos efectos secundarios. ¿Es esto cierto?¿Qué considerar antes de la lista de subclases?

Estoy preguntando si la lista es generalmente mala para la subclase y, de ser así, cuáles son las razones. Alternativamente, ¿qué debería considerar antes de subclasificar la lista en Python?

+2

La lista de subclases no es inherentemente mala, pero hay muchos casos en los que realmente no es lo que quieres hacer. No podemos responder si ese es el caso aquí a menos que nos proporciones detalles. –

Respuesta

17

No hay beneficios en la subclasificación list. Ninguno de los métodos utilizará ningún método que anule, por lo que puede tener errores inesperados. Además, a menudo es confuso hacer cosas como self.append en lugar de self.foos.append o especialmente self[4] en lugar de self.foos[4] para acceder a sus datos. Puede hacer que algo funcione exactamente como una lista o (mejor) sin embargo, como una lista que realmente quiere mientras que simplemente subclases object.

+3

¿Qué sucede si queremos agregar un atributo a una lista? Por ejemplo, supongamos que tenemos mylist = []. Queremos algo como mylist.x = 3. – riza

+1

@Selinap, en un caso en el que quería que mi estado incluyera una lista de algo y un int, probablemente usaría la composición. Usar la herencia para eso abre la confusión en la escritura, la confusión en el uso, y realmente no gana nada. –

+2

Esto parece ser falso de Python 3. Estos contienen ['collections.UserList'] (https://docs.python.org/3.4/library/collections.html#collections.UserList) explícitamente para este propósito. Incluso sugiere que la subclasificación de la lista es posible ahora: "La necesidad de esta clase ha sido parcialmente suplantada por la capacidad de subclase directamente desde la lista;" (Entiendo que este es un tema antiguo y los comentarios anteriores probablemente fueron ciertos mientras estaban escritos, solo quiero dejar esto en claro para las personas que encuentran esta pregunta ahora) – Claude

11

Creo que la primera pregunta que me haría es: "¿Mi nuevo objeto realmente es una lista?". ¿Camina como una lista, habla como una lista? ¿O es algo más?

Si se trata de una lista, todos los métodos de lista estándar deberían tener sentido.

Si los métodos de lista estándar no tienen sentido, entonces su objeto debe contener una lista, no ser una lista.

En el viejo python (2.2?) La lista de subclases era una mala idea por varias razones técnicas, pero en un python moderno está bien.

+4

+1 Heredar solo cuando realmente tiene 100% de sentido, de lo contrario, componer. – delnan

+0

En cuanto a los efectos secundarios, ¿estaba un poco desactualizado? Los datos están contenidos en una lista, pero hay muchos otros métodos específicos que necesito exceder para hacer una serie de cosas. –

+0

sí, heredar para relaciones "is-a", componer para casi todo lo demás. –

6

Nick es correcto. Además, aunque no puedo hablar con Python, en otros lenguajes de OO (Java, Smalltalk) la creación de subclases de una lista es una mala idea. Se debe evitar la herencia en general y, en su lugar, se debe usar la composición de la delegación.

En su lugar, realiza una clase contenedora y delega llamadas a la lista. La clase de contenedor tiene una referencia a la lista e incluso puede exponer las llamadas y devoluciones de la lista en sus propios métodos. Esto agrega flexibilidad y le permite cambiar la implementación (un tipo de lista diferente o estructura de datos) más tarde sin romper ningún código. Si desea que su lista haga cosas diferentes de tipo listy, su contenedor puede hacer esto y usar la lista simple como una estructura de datos simple. Imagine si tenía 47 usos diferentes de listas. ¿De verdad quieres mantener 47 subclases diferentes? En cambio, puede hacerlo a través del contenedor y las interfaces. Una clase para mantener y permitir que las personas llamen a sus métodos nuevos y mejorados a través de la (s) interfaz (es) con la implementación que queda oculta.

17

El abstract base classes proporcionado en el módulo collections, particularmente MutableSequence, puede ser útil cuando se implementan clases similares a listas. Estos están disponibles en Python 2.6 y versiones posteriores.

Con ABCs puede implementar la funcionalidad "core" de su clase y le proporcionará los métodos que lógicamente dependen de lo que haya definido.

Por ejemplo, la aplicación de __getitem__ en una clase derivada de collections.Sequence será suficiente para proporcionar su clase con __contains__, __iter__, y otros métodos.

Es posible que desee utilizar un objeto de lista incluida para realizar el trabajo pesado.

+1

Desde Python 3.3+ se ha movido al módulo ['collections.abc'] (https://docs.python.org/3/library/collections.abc.html). – xmedeko

Cuestiones relacionadas