Wenn Sie die Angewohnheit haben, Quellcode zu lesen, werden Sie möglicherweise feststellen, dass Anweisungen mit dem Schlüsselwort „with“ häufig in einigen hervorragenden Codes vorkommen. In welchen Szenarien wird es normalerweise verwendet? Lassen Sie uns heute über Kontext- und Kontextmanager sprechen.
Bei Systemressourcen wie Dateien, Datenbankverbindungen und Sockets muss die Anwendung, nachdem sie diese Ressourcen geöffnet und die Geschäftslogik ausgeführt hat, die Ressource schließen (trennen).
Zum Beispiel öffnet das Python-Programm eine Datei und schreibt Inhalte in die Datei. Nach dem Schreiben muss die Datei geschlossen werden. In extremen Fällen kann der Fehler „Zu viele geöffnete Dateien“ auftreten, da die maximale Anzahl von Dateien, die das System zu öffnen erlaubt, begrenzt ist.
In ähnlicher Weise kann für die Datenbank, wenn zu viele Verbindungen vorhanden sind und diese nicht rechtzeitig geschlossen werden, „Keine Verbindung zum MySQL-Server möglich. Zu viele Verbindungen“ angezeigt werden, weil die Datenbankverbindung ist eine sehr teure Ressource, die nicht unbegrenzt erstellt werden kann.
Sehen wir uns an, wie man eine Datei richtig schließt.
def m1(): f = open("output.txt", "w") f.write("python之禅") f.close()
Es besteht ein potenzielles Problem beim Schreiben wie diesem. Wenn während des Schreibaufrufs eine Ausnahme auftritt, kann nachfolgender Code nicht weiter ausgeführt werden . Die Close-Methode kann nicht normal aufgerufen werden, sodass die Ressourcen immer vom Benutzer des Programms freigegeben werden. Wie können wir den Code verbessern?
def m2(): f = open("output.txt", "w") try: f.write("python之禅") except IOError: print("oops error") finally: f.close()
Die verbesserte Version des Programms besteht darin, mithilfe der try/finally-Anweisung zu versuchen, den Code dort zu erfassen, wo Ausnahmen auftreten können bedeutet: Wenn im Programm im Try-Codeblock eine Ausnahme auftritt, wird nachfolgender Code nicht mehr ausgeführt und springt direkt zum Except-Codeblock. Egal was passiert, der Code im „finally“-Block wird schließlich ausgeführt. Daher wird die Datei definitiv geschlossen, solange im Final-Code „close“ steht.
def m3(): with open("output.txt", "r") as f: f.write("Python之禅")
Eine prägnantere und elegantere Möglichkeit ist die Verwendung des Schlüsselworts with. Der Rückgabewert der open-Methode wird der -Variablen f zugewiesen. Beim Verlassen des with-Codeblocks ruft das System automatisch die f.close()-Methode auf try/finally-Anweisung. Was ist also das Umsetzungsprinzip? Bevor wir über das Prinzip von with sprechen, sollte ein anderes Konzept einbezogen werden, nämlich der Kontextmanager.
Jedes Objekt, das die Methoden enter() und exit() implementiert, kann als aufgerufen werden Kontextmanager: Das Kontextmanagerobjekt kann das Schlüsselwort with verwenden. Offensichtlich implementieren Dateiobjekte auch Kontextmanager.
Wie implementiert das Dateiobjekt diese beiden Methoden? Wir können die Implementierung einer eigenen Dateiklasse simulieren und die Klasse die Methoden enter() und exit() implementieren lassen.
class File(): def init(self, filename, mode): self.filename = filename self.mode = mode def enter(self): print("entering") self.f = open(self.filename, self.mode) return self.f def exit(self, *args): print("will exit") self.f.close()
enter() Methode gibt das Ressourcenobjekt zurück, hier ist das Dateiobjekt, das Sie gerade öffnen möchten, exit() Die Methode erledigt einige Aufräumarbeiten.
Da die File-Klasse einen Kontextmanager implementiert, können Sie jetzt die with-Anweisung verwenden.
with File('out.txt', 'w') as f: print("writing") f.write('hello, python')
Auf diese Weise müssen Sie die Close-Methode nicht explizit aufrufen. Das System ruft sie automatisch auf, auch wenn in der Mitte eine Ausnahme auftritt, die Close Methode wird aufgerufen.
Python bietet auch einen Kontextmanager-Dekorator, der die Implementierung des Kontextmanagers weiter vereinfacht. Die Funktion wird durch yield in zwei Teile geteilt, die Anweisung vor yield wird in der Methode enter ausgeführt, und die Anweisung nach yield wird in der Methode exit ausgeführt . Der Wert unmittelbar nach yield ist der Rückgabewert der -Funktion .
from contextlib import contextmanager @contextmanager def my_open(path, mode): f = open(path, mode) yield f f.close()
Aufruf
with my_open('out.txt', 'w') as f: f.write("hello , the simplest context manager")
Python stellt die Syntax bereit, um die Nachverfolgung zu vereinfachen Die Ressourcenoperation ist eine Alternative zu try/finally und das Implementierungsprinzip basiert auf dem Kontextmanager. Darüber hinaus bietet Python auch einen Kontextmanager-Dekorator, um die Implementierung von Kontextmanagern weiter zu vereinfachen.
Das obige ist der detaillierte Inhalt vonAusführliche Erläuterung des Schlüsselworts „with' und des Kontextmanagers. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!