Problema
Sto lavorando su un progetto Python la cui classe principale è un po '" God Object ". Ci sono così friggin "molti attributi e metodi!
Voglio refactoring della classe.
So Far ...
Per il primo passo, voglio fare qualcosa di relativamente semplice; ma quando ho provato l'approccio più semplice, ha rotto alcuni test ed esempi esistenti.
Fondamentalmente, la classe ha una lista mooolto di attributi - ma posso chiaramente guardarli e pensare, "Questi 5 attributi sono correlati ... Questi 8 sono anche correlati ... e poi c'è il resto."
getattr
Fondamentalmente volevo raggruppare gli attributi correlati in una classe helper dict-like. Ho avuto la sensazione che __getattr__
sarebbe l'ideale per il lavoro. Così ho spostato gli attributi in una classe separata, e, abbastanza sicuro, __getattr__
ha funzionato perfettamente con la sua magia ...
A prima .
Ma poi ho provato a eseguire uno degli esempi. La sottoclasse di esempio tenta di impostare direttamente uno di questi attributi (al livello di classe ). Ma poiché l'attributo non era più "localizzato fisicamente" nella classe genitore, ho ricevuto un errore che diceva che l'attributo non esisteva.
@property
Poi ho letto del decoratore @property
. Ma poi ho anche letto che crea problemi per sottoclassi che vogliono fare self.x = blah
quando x
è una proprietà della classe genitore.
desiderata
- Il codice cliente continua a funzionare utilizzando
self.whatever
, anche se la proprietà% gen_de% del genitore non è "localizzata fisicamente" nella classe (o nell'istanza) stessa. - Raggruppa gli attributi in contenitori dict-like.
- Riduce l'estrema rumorosità del codice nella classe principale.
Ad esempio, I non semplicemente vuoi cambiare questo:
larry = 2
curly = 'abcd'
moe = self.doh()
In this:
larry = something_else('larry')
curly = something_else('curly')
moe = yet_another_thing.moe()
... perché è ancora rumoroso. Anche se questo rende con successo un semplice attributo in qualcosa che può gestire i dati, l'originale aveva 3 variabili e la versione ottimizzata ha ancora 3 variabili.
Tuttavia, mi andrebbe bene qualcosa del genere:
stooges = Stooges()
E se una ricerca per whatever
fallisce, qualcosa controlla self.larry
e verifica se stooges
è presente. (Ma deve funzionare anche se una sottoclasse prova a fare larry
a livello di classe.)
Sommario
- Desideri sostituire i relativi gruppi di attributi in una classe genitore con un singolo attributo che memorizza tutti i dati altrove
- Vuoi lavorare con il codice client esistente che utilizza (ad esempio)
larry = 'blah'
a livello di classe - Vuoi continuare a consentire alle sottoclassi di estendere, sovrascrivere e modificare questi attributi refactored senza sapere che qualcosa è cambiato
È possibile? O sto abbaiando dall'albero sbagliato?