2010-02-04 11 views
9

¿Qué tan malo es redefinir un método de clase de otro módulo de terceros en Python?¿Qué tan malo es anular un método de un módulo de terceros?

De hecho, los usuarios pueden crear matrices que contienen NumPy numbers with uncertainty; idealmente, me gustaría que su código se ejecute sin modificaciones (en comparación con cuando el código manipula matrices flotantes); en particular, sería grande si la inversa de la matriz m todavía podría ser obtenido con m.I, a pesar del hecho de que m.I tienen que ser calculados con mi propio código (el método original I no funciona, en general).

¿Es muy grave para redefinir numpy.matrix.I? Por un lado, altera el código de terceros, lo que no me gusta, ya que puede no ser robusto (¿y si otros módulos hacen lo mismo? ...). Otro problema es que el nuevo numpy.matrix.I es un contenedor que implica una pequeña sobrecarga cuando se puede aplicar la matriz original numpy.matrix para obtener la matriz inversa.

Está subclassing matrices NumPy y sólo cambiar su método I mejor? esto obligaría a los usuarios a actualizar su código y crear matrices de números con incertidumbre con m = matrix_with_uncert(…) (en lugar de seguir usando numpy.matrix(…), como para una matriz de carrozas), pero tal vez esto sea un inconveniente que debería aceptarse en aras de la solidez. Las inversiones de matrices aún se pueden realizar con m.I, lo cual es bueno ... Por otro lado, sería bueno si los usuarios pudieran construir todas sus matrices (de flotantes o de números con incertidumbres) directamente con numpy.matrix(), sin tener que molestarse en verificar los tipos de datos. .

¡Algún comentario o enfoque adicional sería bienvenido!

Respuesta

11

La subclasificación (que implica anulación, como se usa generalmente el término) es generalmente preferible a "parche de monos" (relleno de métodos alterados en clases o módulos existentes), incluso cuando este último está disponible (tipos incorporados , es decir, los implementados en C, pueden protegerse contra parches de mono, y la mayoría de ellos lo hacen).

Por ejemplo, si su funcionalidad depende del parche de monos, se interrumpirá y detendrá las actualizaciones si en algún momento se actualiza la clase que está siendo implementada en C (para acelerar o defender específicamente contra el parche de mono)) Mantenedores de paquetes de terceros odian mono-parches, ya que significa que reciben informes de errores falsos de usuarios desafortunados que (sin saberlo) son, de hecho, utilizando un mono-parche con errores, que rompe el paquete de terceros, cuando éste (a menos de mono roto sabio) es perfecto. Ya has comentado sobre el posible golpe de rendimiento.

Conceptualmente, una "matriz de números con incertidumbre" es un concepto diferente de una "matriz de números". La subclasificación expresa esto limpiamente, el parche de monos intenta ocultarlo. Esa es realmente la raíz de lo que está mal con el parche de monos en general: un canal encubierto que opera a través de medios ocultos y globales, sin claridad ni transparencia. Todos los muchos problemas prácticos descienden en cierto sentido de este problema conceptual raíz.

I fuertemente le instamos a que rechace el parche de mono a favor de soluciones limpias como la creación de subclases.

+0

Gracias por esta descripción lúcida del mono de parches y de sus problemas potenciales! Debo decir que NumPy fomenta la definición de "matrices de algo" apoyándolas ('numpy.array ([any_object])'). Por lo tanto, diría que "matrices de cualquier tipo de objeto" es un concepto muy respaldado por NumPy-element-wise Además, se admite automáticamente. Dicho esto, ¡me suscribo completamente al resto de su respuesta! – EOL

1

En general, es perfectamente aceptable para reemplazar los métodos que son ...

  • permiten intencionalmente anulaciones
  • De manera que documentan (satisfaciendo LSP No le hará daño)

Si Ambas condiciones se cumplen, y la anulación debe ser segura.

+1

enlace interesante sobre LSP! – EOL

1

Depende de lo que quiere decir con "redefinir". Obviamente, puedes usar tu propia versión, sin problemas. También puedes redefinirlo subclasificando si se trata de un método.

También puede hacer un nuevo método, y el parche en la clase, una práctica conocida como monkey_patching. De este modo:

from amodule import aclass 

def newfunction(self, param): 
    do_something() 

aclass.oldfunction = newfunction 

Esto hará que todas las instancias de AClass utilizar su nueva función en lugar de la antigua, incluidos los casos en los módulos "cuarta parte". Esto funciona y es muy útil, pero se considera muy desagradable y una opción de último recurso. Esto se debe a que no hay nada en el código de aclass que sugiera que ha anulado el método, por lo que es difícil depurarlo. Y aún peor, cuando dos módulos hacen el mismo parche. Entonces realmente se confunden.

Cuestiones relacionadas