Come devo restituire i valori interessanti da un con-dichiarazione?
-
22-08-2019 - |
Domanda
C'è un modo migliore di utilizzare globali per ottenere i valori interessanti da un contesto manager?
@contextmanager
def transaction():
global successCount
global errorCount
try:
yield
except:
storage.store.rollback()
errorCount += 1
else:
storage.store.commit()
successCount += 1
Altre possibilità:
-
single
sorta di variabili globali ...
-
tuple come argomento al contesto Manager
rende la funzione più specifica a un problema / meno riutilizzabile
-
istanza che contiene gli attributi specifici come argomento al contesto Manager
stessi problemi del tuple, ma più leggibile
-
genera un'eccezione alla fine del contesto gestore che contiene i valori.
pessima idea
Soluzione
http://docs.python.org/reference/datamodel.html # contesto-manager
Creare una classe che detiene i conteggi di successo e di errore, e che implementa i metodi __enter__
e __exit__
.
Altri suggerimenti
penso ancora che si dovrebbe essere la creazione di una classe per tenerti conta errore / di successo, come ho detto in voi ultima domanda . Sto indovinando avete la propria classe, quindi basta aggiungere qualcosa di simile ad esso:
class transaction:
def __init__(self):
self.errorCount = 0
self.successCount = 0
def __enter__(*args):
pass
def __exit__(self, type, value, traceback):
if type:
storage.store.rollback()
self.errorCount += 1
else:
storage.store.commit()
self.successCount += 1
(type
è Nessuno se non ci sono eccezioni, una volta che invocano il contextmanager
)
E allora probabilmente sta già utilizzando questo da qualche parte, che richiamerà l'contextmanager
ed eseguire il codice __exit__()
. Modifica:. Come ha commentato Eli, solo creare una nuova istanza di transazione quando si desidera ripristinare le coutners
t = transaction()
for q in queries:
with t:
t.execute(q)
"tupla come argomento al contesto Manager
rende la funzione più specifica a un problema / meno riutilizzabile "
False.
In questo modo il manager contesto mantenere lo stato.
Se non implementare qualcosa di più di questo, sarà riutilizzabile.
Tuttavia, non si può effettivamente utilizzare una tupla perché è immutabile. Avete bisogno di qualche collezione mutevole. Dizionari e definizioni di classe vengono in mente.
Di conseguenza, l'implementazione consigliato è
"istanza che contiene gli attributi specifici come argomento al contesto manager"
Una definizione semplice classe con due attributi è tutto ciò che serve. Tuttavia, lo stato di transazione è stateful ed è necessario mantenere lo stato da qualche parte.
class Counters(dict):
SUCCEED= 0
FAIL= 1
def __init__( self ):
self[ self.SUCCEED ]= 0
self[ self.FAIL ]= 0
def increment( self, status ):
self[status] += 1
class Transaction(object):
def __init__( self, worker, counters ):
self.worker= worker
self.counters= counters
def __enter__( self ):
self.counters.status= None
def process( self, *args, **kw ):
status= self.worker.execute( *args, **kw )
self.counters.increment( status )
def __exit__( self ):
pass
counts= Counters()
for q in queryList:
with Transaction(execQuery,counts) as t:
t.process( q )
print counts