python list subclassing

python - ¿Qué considerar antes de subclasificar la lista?



subclassing (4)

Hace poco revisé un problema de codificación que estaba teniendo y alguien que miraba el código dijo 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 efectos secundarios negativos. ¿Es esto cierto?

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


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

Si es una lista, entonces 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 la antigua lista de subclases de python (2.2?) Era una mala idea por varias razones técnicas, pero en un python moderno está bien.


Las clases base abstractas proporcionadas en el módulo de collections , particularmente MutableSequence , pueden ser útiles cuando se implementan clases similares a listas. Estos están disponibles en Python 2.6 y versiones posteriores.

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

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

Es posible que aún desee utilizar un objeto de lista contenida para hacer el trabajo pesado.


Nick es correcto. Además, si bien no puedo hablar con Python, en otros lenguajes OO (Java, Smalltalk) subclasificar una lista es una mala idea. Debe evitarse la herencia en general y, en su lugar, debe utilizarse la composición de delegación.

Más bien, haces una clase contenedora y delegas las llamadas a la lista. La clase contenedora tiene una referencia a la lista e incluso puede exponer las llamadas y devoluciones de la lista con sus propios métodos. Esto agrega flexibilidad y le permite cambiar la implementación (un tipo de lista o estructura de datos diferente) más adelante sin romper ningún código. Si desea que su lista haga diferentes cosas de tipo listy, su contenedor puede hacer esto y usar la lista simple como una estructura de datos simple. Imagínate si tuvieras 47 usos diferentes de listas. ¿Realmente quieres mantener 47 subclases diferentes? En su lugar, podría hacer esto 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 oculta.


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