Wie soll ich interessante Werte zurückgeben aus einer mit-Anweisung?
-
22-08-2019 - |
Frage
Gibt es einen besseren Weg, als Globals mit interessanten Werte aus einem Kontext-Manager zu bekommen?
@contextmanager
def transaction():
global successCount
global errorCount
try:
yield
except:
storage.store.rollback()
errorCount += 1
else:
storage.store.commit()
successCount += 1
Weitere Möglichkeiten:
-
Singletons
Art von Globals ...
-
Tupel als Argument für den Kontext-Manager
macht die Funktion spezifischer auf ein Problem / weniger wiederverwendbar
-
Instanz, die die spezifischen Eigenschaften als Argument für den Kontext-Manager
hältgleiche Probleme wie das Tupel, aber mehr lesbar
-
eine Ausnahme am Ende des Kontext-Managers erhöht die Werte zu halten.
wirklich schlechte Idee
Lösung
Siehe http://docs.python.org/reference/datamodel.html # kontext Manager
Erstellen Sie eine Klasse, die den Erfolg und Fehlerzahlen hält, und welche implementiert die __enter__
und __exit__
Methoden.
Andere Tipps
Ich denke immer noch, sollten Sie eine Klasse werden Erstellen Sie Fehler / Erfolg zählt zu halten, wie ich sagte, in Ihnen einen href <= "https://stackoverflow.com/questions/877440/try-except-except-how- zu vermeiden wiederholendes-code "> letzte Frage . Ich schätze, dass Sie Ihre eigene Klasse haben, also nur so etwas wie diese, um es hinzuzufügen:
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
ist keine, wenn es keine Ausnahmen sind, wenn die contextmanager
Aufruf)
Und dann sind Sie wahrscheinlich schon diese irgendwo verwenden, die die contextmanager
aufrufen und Ihre __exit__()
Code ausführen. Edit:. Wie Eli kommentierte erstellen nur eine neue Transaktion Beispiel, wenn Sie die coutners zurücksetzen möchten
t = transaction()
for q in queries:
with t:
t.execute(q)
"Tupel als Argument für den Kontext-Manager
macht die Funktion spezifischer auf ein Problem / weniger wiederverwendbar "
Falsch.
Dies macht den Kontextmanager Zustand beibehalten.
Wenn Sie nichts implementieren mehr als das, wird es wieder verwendbar sein.
Sie können jedoch tatsächlich nicht ein Tupel verwenden, weil es unveränderlich ist. Sie müssen einige wandelbar Sammlung. Wörterbücher und Klassendefinitionen in den Sinn kommen.
Folglich ist die empfohlene Implementierung ist
„Instanz, die die spezifischen Eigenschaften als Argument für den Kontextmanager hält“
Eine einfache Klassendefinition mit zwei Attributen ist alles, was Sie brauchen. Allerdings ist Ihr Transaktionsstatus Stateful und Sie müssen Zustand irgendwo halten.
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