Schließung

Es gibt viele Artikel im Internet, in denen Python-Verschlüsse vorgestellt werden. In diesem Artikel erfahren Sie mehr über Verschlüsse, indem Sie ein Anforderungsproblem lösen.

Die Voraussetzung ist, dass wir unsere Lernzeit weiterhin in Minuten aufzeichnen müssen. Es ist so, als würde ich 2 Minuten lang lernen und 2 Minuten zurückgeben. Nach einer Weile lerne ich 10 Minuten lang und dann 12 Minuten zurück. Die Lernzeit wird auf diese Weise akkumuliert.

Angesichts dieser Nachfrage erstellen wir normalerweise eine globale Variable, um die Zeit aufzuzeichnen, und verwenden dann eine Methode, um jede Lernzeit hinzuzufügen, normalerweise in der folgenden Form:

time = 0
def insert_time(min):
    time = time + min
    return  time
print(insert_time(2))
print(insert_time(10))

Denken Sie ernsthaft darüber nach Gibt es ein Problem?

Eigentlich wird dadurch ein Fehler in Python gemeldet. Der folgende Fehler wird gemeldet:

UnboundLocalError: local variable 'time' referenced before assignment

Das liegt daran, dass in Python die Variable zu einer lokalen Variablen wird, wenn eine Funktion denselben Namen wie eine globale Variable verwendet und den Wert der Variablen ändert Dies führt dazu, dass wir in der Funktion darauf verweisen, ohne es zu definieren, sodass dieser Fehler gemeldet wird.

Was sollten Sie tun, wenn Sie wirklich auf eine globale Variable verweisen und diese in einer Funktion ändern möchten?

Wir können das globale Schlüsselwort verwenden und die spezifischen Änderungen sind wie folgt:

time = 0
def insert_time(min):
    global  time
    time = time + min
    return  time
print(insert_time(2))
print(insert_time(10))

Das Ausgabeergebnis ist wie folgt:

2
12

Hier werden jedoch globale Variablen verwendet. Wir können in der Entwicklung unser Bestes geben. Vermeiden Sie die Verwendung globaler Variablen so weit wie möglich. Da verschiedene Module und Funktionen frei auf globale Variablen zugreifen können, können globale Variablen unvorhersehbar sein. Beispielsweise ändert Programmierer A den Wert der globalen Variablen Zeit, und dann ändert Programmierer B auch die Zeit. Wenn ein Fehler vorliegt, ist es schwierig, ihn zu finden und zu korrigieren.

Globale Variablen verringern die Vielseitigkeit zwischen Funktionen oder Modulen. Verschiedene Funktionen oder Module hängen von globalen Variablen ab. Ebenso verringern globale Variablen die Lesbarkeit des Codes, und Leser wissen möglicherweise nicht, dass eine bestimmte aufgerufene Variable eine globale Variable ist.

Gibt es einen besseren Weg?

Zu diesem Zeitpunkt verwenden wir Schließungen, um es zu lösen. Schauen wir uns den Code direkt an:

time = 0
def study_time(time):
    def insert_time(min):
        nonlocal  time
        time = time + min
        return time
    return insert_time
f = study_time(time)
print(f(2))
print(time)
print(f(10))
print(time)

Das Ausgabeergebnis ist wie folgt:

2
0
12
0

Die direkteste Manifestation hier ist die globale Variable time. Sie wurde am Ende noch nicht geändert, was auf die Verwendung äußerer (nicht globaler) Variablen in Funktionen oder anderen Bereichen hinweist. Was ist also der spezifische Ausführungsprozess des obigen Codes? Wir können uns das Bild unten ansehen:

a4e16c80e1df62cb932f66f1b8b91c9.png

Dies ist ein Verhalten, bei dem auf Variablen im lokalen Bereich der externen Funktion im lokalen Bereich der internen Funktion zugegriffen werden kann heißt: Schließung. Eine direktere Möglichkeit, dies auszudrücken, besteht darin, dass bei der Rückgabe einer Funktion als Objekt externe Variablen einbezogen werden, die einen Abschluss bilden. Der k

-Abschluss vermeidet die Verwendung globaler Variablen. Darüber hinaus ermöglichen Abschlüsse die Verknüpfung einer Funktion mit einigen Daten (Umgebung), mit denen sie arbeitet. Und die Verwendung von Verschlüssen kann den Code eleganter machen. Und die im nächsten Artikel erwähnten Dekoratoren werden auch basierend auf Verschlüssen implementiert.

An dieser Stelle wird es eine Frage geben: Glauben Sie, dass es sich um eine Schließung oder eine Schließung handelt? Gibt es eine Möglichkeit zu überprüfen, ob diese Funktion ein Abschluss ist?

Ja, alle Funktionen haben ein __closure__-Attribut. Wenn die Funktion ein Abschluss ist, gibt sie ein aus Zellen bestehendes Tupelobjekt zurück. Die cell_contents-Eigenschaft des Zellobjekts ist die im Abschluss gespeicherte Variable.

Lass es uns ausdrucken und erleben:

time = 0
def study_time(time):
    def insert_time(min):
        nonlocal  time
        time = time + min
        return time
    return insert_time
f = study_time(time)
print(f.__closure__)
print(f(2))
print(time)
print(f.__closure__[0].cell_contents)
print(f(10))
print(time)
print(f.__closure__[0].cell_contents)

Das gedruckte Ergebnis ist:

(<cell at 0x0000000000410C48: int object at 0x000000001D6AB420>,)
2
0
2
12
0
12

Aus dem gedruckten Ergebnis können wir erkennen, dass der übergebene Wert immer in gespeichert wird Der Zellinhalt des Abschlusses ist also das größte Merkmal des Abschlusses. Er kann die Variablen der übergeordneten Funktion an ihre intern definierte Funktion binden. Selbst wenn die übergeordnete Funktion, die den Abschluss generiert hat, freigegeben wurde, ist der Abschluss weiterhin vorhanden.

Der Prozess des Schließens ähnelt tatsächlich dem Generieren einer Instanz (Abschluss) durch eine Klasse (übergeordnete Funktion). Der Unterschied besteht darin, dass die übergeordnete Funktion erst ausgeführt wird, wenn sie aufgerufen wird Die Klasse wird in der Datei ausgeführt, und der Bereich wird im Allgemeinen nach der Ausführung des Programms freigegeben. Daher werden für einige Funktionen, die wiederverwendet werden müssen und nicht als Klasse definiert werden können, weniger Ressourcen beansprucht als die Verwendung von Klassen und ist leichter und flexibler.

Weiter lernen
||
einreichenCode zurücksetzen