Problema
Estoy trabajando en un proyecto de Python cuya clase principal es un poco " God Object ". ¡Hay tantos malditos atributos y métodos!
Quiero refactorizar la clase.
Hasta aquí…
Para el primer paso, quiero hacer algo relativamente simple; pero cuando probé el enfoque más directo, rompió algunas pruebas y ejemplos existentes.
Básicamente, la clase tiene una lista muuuucha larga de atributos, pero puedo verlos claramente y pensar: "Estos 5 atributos están relacionados ... Estos 8 también están relacionados ... y luego está el resto".
getattr
Básicamente, solo quería agrupar los atributos relacionados en una clase auxiliar tipo dict. Tenía la sensación de __getattr__que sería ideal para el trabajo. Así que moví los atributos a una clase separada y, efectivamente, __getattr__trabajé su magia perfectamente bien ...
En primer lugar .
Pero luego intenté ejecutar uno de los ejemplos. La subclase de ejemplo intenta establecer uno de estos atributos directamente (a nivel de clase ). Pero como el atributo ya no estaba "físicamente ubicado" en la clase principal, recibí un error que decía que el atributo no existía.
@propiedad
Luego leí sobre el @propertydecorador. Pero también leí que crea problemas para las subclases que quieren hacer self.x = blahcuando xes una propiedad de la clase principal.
Deseado
- Haga que todo el código del cliente continúe funcionando
self.whatever, incluso si lawhateverpropiedad del padre no está "físicamente ubicada" en la clase (o instancia) en sí misma. - Agrupe atributos relacionados en contenedores tipo dict.
- Reduzca el ruido extremo del código en la clase principal.
Por ejemplo, no quiero simplemente cambiar esto:
larry = 2
curly = 'abcd'
moe = self.doh()
Dentro de esto:
larry = something_else('larry')
curly = something_else('curly')
moe = yet_another_thing.moe()
... porque eso sigue siendo ruidoso. Aunque eso convierte con éxito un atributo simple en algo que puede administrar los datos, el original tenía 3 variables y la versión modificada todavía tiene 3 variables.
Sin embargo, estaría bien con algo como esto:
stooges = Stooges()
Y si una búsqueda self.larryfalla, algo verificaría stoogesy vería si larryestá allí. (Pero también debe funcionar si una subclase intenta hacerlo larry = 'blah'a nivel de clase).
Resumen
- Desea reemplazar grupos de atributos relacionados en una clase principal con un solo atributo que almacena todos los datos en otro lugar
- Quiere trabajar con el código de cliente existente que usa (por ejemplo)
larry = 'blah'a nivel de clase - Desea continuar permitiendo que las subclases extiendan, anulen y modifiquen estos atributos refactorizados sin saber que algo ha cambiado.
es posible? ¿O estoy ladrando el árbol equivocado?