In genere, si dispone di un tipo di oggetto che rappresenta la cosa che utilizza un database (ad esempio un'istanza di MyWebServer
) e si effettua la connessione al database come membro di tale oggetto.
Se si dispone invece di tutta la logica in una specie di funzione, rendere la connessione locale a tale funzione. (Questo non è troppo comune in molti altri linguaggi, ma in Python ci sono spesso buoni modi per concludere lavori di stato a più stadi in una singola funzione di generatore.)
Se si dispone di tutta la documentazione di database sparsi tutti sopra il posto, quindi basta usare una variabile globale invece di un singleton. Sì, i globali sono cattivi, ma i singleton sono altrettanto cattivi e più complicati. Ci sono alcuni casi in cui sono utili, ma molto rari. (Questo non è necessariamente vero per altre lingue, ma è per Python.) E il modo per sbarazzarsi del globale è ripensare la progettazione. C'è una buona probabilità che stai in modo efficace utilizzando un modulo come un (singolo) oggetto, e se si pensa che attraverso, probabilmente si può trovare una buona classe o funzione per avvolgere in su in.
Ovviamente semplicemente spostando tutti i tuoi globali in attributi di classe e @classmethod
ti sta dando solo globali con uno spazio dei nomi differente. Ma trasferirli negli attributi di istanza è una storia diversa. Questo ti dà un oggetto che puoi passare e, se necessario, un oggetto puoi avere 2 (o forse anche 0 in alcune circostanze), collegare un blocco, serializzare, ecc.
In molti tipi di applicazioni , stai per finire con una singola istanza di qualcosa - ogni app Qt della GUI ha esattamente uno MyQApplication
, quasi ogni server Web ha esattamente uno MyWebServer
, ecc. Non importa come lo chiami, è effettivamente un singleton o globale. E se vuoi, puoi semplicemente spostare tutto in attributi di quell'oggetto divino.
Ma solo perché è possibile fare ciò non significa che si . Hai ancora parametri di funzione, variabili locali, globali in ogni modulo, altre classi (non megalitiche) con i loro attributi di istanza, ecc., E dovresti usare qualunque cosa sia appropriata per ogni valore.
Ad esempio, supponiamo che il tuo MyWebServer
crei una nuova istanza ClientConnection
per ogni nuovo client che si connette a te. Potresti fare in modo che le connessioni scrivano MyWebServer.instance.db.execute
ogni volta che vogliono eseguire una query SQL ... ma potresti anche solo passare il self.db
al costruttore ClientConnection
, e ogni connessione poi fa solo self.db.execute
. Quindi qual è il migliore? Bene, se lo fai in questo modo, rende il tuo codice molto più facile da estendere e refactoring. Se si desidera eseguire il bilanciamento del carico su 4 database, è sufficiente modificare il codice in un'unica posizione (dove inizializza ogni ClientConnection
) anziché 100 (ogni volta che ClientConnection
accede al database). Se si desidera convertire la propria app Web monolitica in un contenitore WSGI, non è necessario modificare alcun codice ClientConnection
eccetto forse il costruttore. E così via.
tipo di app = class.webapp(); app.dbconn = class.dbconn()? Alla fine è davvero così diverso da un singleton? – AlessandroEmm
@AlessandroMeyer: fammi modificare la risposta per rispondere. – abarnert