Sí, es útil y que sirve un propósito, pero también es bastante raro tener que hacer esto. Si crees que necesitas parchear las clases después de haberlas definido, siempre debes detenerte y considerar si realmente es la mejor.
Una situación es el parche de monos.He hecho esto en un gran sistema Plone donde algunos métodos requieren ajustes menores, pero simplemente no había una manera fácil de anular el comportamiento normalmente. En esa situación en la que tiene una biblioteca compleja, proporciona una manera fácil de inyectar un comportamiento nuevo o modificado sin tener que cambiar la biblioteca original.
La otra situación que me viene a la mente es cuando quieres una gran cantidad de métodos que se pueden generar automáticamente. p.ej. Pruebas basadas en datos.
def createTest(testcase, somedata, index):
def test(self):
"Do something with somedata and assert a result"
test_name = "test_%d" % index
setattr(testcase, test_name, test)
for index, somedata in enumerate(somebigtable):
createTest(MyTestCase, somedata, index)
cuando MyTestCase es un unittest.TestCase usted podría tener una prueba que va a través de todos los datos, pero se detiene en el primer fallo y de tener que tratar de averiguar qué línea de datos falló. Al crear dinámicamente los métodos, todas las pruebas se ejecutan por separado y el nombre de la prueba le dice cuál falló (el original del código anterior realmente construyó un nombre más significativo que incluye algunos de los datos, así como el índice).
No se puede hacer eso dentro del cuerpo de la clase porque no hay forma de hacer referencia a la clase o a su diccionario antes de que se complete la definición. Sin embargo, puede hacer algo similar con una metaclase, ya que le permite modificar el dictado de clase antes de crear la clase y, a veces, esa es una forma más limpia de hacer el mismo tipo de cosas.
La otra cosa a tener en cuenta es que hay situaciones en las que esto no funcionará. Algunos métodos especiales __xxx__
no pueden anularse después de que se haya creado la clase: la definición original se guarda internamente en algún lugar que no sea el __dict__
de la clase, por lo que se pueden ignorar los cambios que realice más adelante. Además, si se trabaja con metaclases, a veces las funciones adicionales no obtendrán el tratamiento que la metaclase les dé a los atributos como parte de la definición de la clase.
¡Interesante! Esto también sugiere que otro valor podría estar moviendo la definición de métodos que no son centrales para la clase en otro lugar. Obviamente para situaciones especiales. –