Alle bisherigen Antworten liefern nicht, was (ich glaube) OP direkt wollen .
(Ich denke) OP möchte so etwas:
Das ist, was ich vorhabe, es mag nicht sehr robust sein, aber ich denke, es liegt am nächsten bei OPs Absicht.
%Vor% Dies gibt genau die gleiche Ausgabe wie oben gezeigt, solange with
in derselben Zeile mit X()
liegt, wenn der Kontextmanager verwendet wird.
Es gibt keinen direkten Weg, soweit ich weiß. Sie können jedoch ein boolesches Flag verwenden, um zu überprüfen, ob __enter__
aufgerufen wurde, bevor die tatsächlichen Methoden in den Objekten aufgerufen wurden.
Wenn Sie es mit with
verwenden,
Sie werden
erhalten %Vor% Wenn Sie jedoch ein Objekt manuell erstellen und do_something
aufrufen,
Sie werden
erhalten %Vor% Hinweis: Dies ist keine feste Lösung. Jemand kann direkt __enter__
-Methode aufrufen, bevor andere Methoden aufgerufen werden, und die Methode __exit__
wird in diesem Fall niemals aufgerufen.
Wenn Sie diese Überprüfung nicht in jeder Funktion wiederholen möchten, können Sie sie zu einem Dekorateur machen, wie dies hier beschrieben wird.
%Vor% Es gibt keine narrensichere Methode, um sicherzustellen, dass eine Instanz in einer with
-Klausel erstellt wird. Sie können jedoch eine Instanz in der Methode __enter__
erstellen und diese anstelle von self
; Dies ist der Wert, der in x
zugewiesen wird. Daher können Sie X
als Factory betrachten, die die tatsächliche Instanz in ihrer __enter__
-Methode erstellt, etwa wie folgt:
Natürlich ist dies immer noch wiederverwendbar, aber jede with
Anweisung würde eine neue Instanz erstellen.
Natürlich kann man __enter__
manuell aufrufen oder einen Verweis auf das ActualInstanceClass
erhalten, aber es wäre mehr missbrauchen anstatt zu verwenden.
Für einen noch geruchsärmeren Ansatz erzeugt das X()
beim Aufruf tatsächlich eine XFactory
-Instanz anstelle einer X
-Instanz; und diese wiederum erstellt, wenn sie als Kontextmanager verwendet wird, die ActualX
-Instanz, die die Unterklasse von X
ist, daher wird isinstance(x, X)
den Wert true zurückgeben.
Du könntest das weiterführen und XFactory
eine tatsächliche X
-Instanz mit einem speziellen Schlüsselwort-Argument für __new__
erstellen lassen, aber ich halte es für zu schwarz, um nützlich zu sein.
Leider können Sie nicht sehr sauber.
Kontextmanager benötigen die Methoden __enter__
und __exit__
, damit Sie eine Membervariable für die Klasse zum Einchecken Ihres Codes zuweisen können.
Der statusbehaftete Objektansatz hat den zusätzlichen Vorteil, dass er später feststellen kann, ob die __exit__
-Methode aufgerufen wurde, oder um Methodenanforderungen in späteren Aufrufen sauber zu behandeln:
Hier ist ein Decorator, der automatisiert, dass Methoden nicht außerhalb eines Kontextmanagers aufgerufen werden:
%Vor%Und hier ist ein Beispiel dafür:
%Vor%Dies wurde als Antwort auf diese doppelte Frage .
Tags und Links python with-statement