Heim > Artikel > Backend-Entwicklung > Standardumfang und -abschlüsse in Python und Lua
Standardumfang
Ich habe vor einiger Zeit Lua gelernt und festgestellt, dass der Standardumfang von Lua dem von Python entgegengesetzt ist. Wenn Lua eine Variable definiert, ist der Standardbereich der Variablen nicht sehr genau. Wenn Lua eine Anweisung wie x = 1 ausführt, wird nur dann nach x gesucht, wenn dies nicht möglich ist find x Globale Variablen werden nur unter bestimmten Umständen definiert. Wenn Python eine Variable definiert, ist der Gültigkeitsbereich der Variablen standardmäßig lokal (aktueller Block). Darüber hinaus kann Lua lokale Variablen definieren, indem beim Definieren der Variablen das lokale Schlüsselwort vor der Variablen hinzugefügt wird. Python verfügt jedoch nicht über ein ähnliches Schlüsselwort und Python-Variablen können nur im aktuellen Block definiert werden.
Wir wissen, dass globale Variablen schlecht sind, lokale Variablen jedoch gut. Sie sollten versuchen, beim Schreiben von Programmen lokale Variablen zu verwenden. Daher dachte ich am Anfang, dass die Konvention von Python besser sei. Ihr Vorteil besteht darin, dass sie weniger Tipparbeit erfordert. Wenn ich Lua-Programme schreibe, sage ich in meinem Herzen immer: „Vergiss das Lokale nicht, vergiss das Lokale nicht.“ Manchmal gehen jedoch ein paar Dinge durch das Netz und verursachen magische Fehler.
Abschluss
Das erste Mal, dass mir das Problem des Standardbereichs von Python auffiel, war die Verwendung von Abschlüssen. In Bezug auf Abschlüsse gibt es einen Code im Lua-Tutorial:
function new_counter() local n = 0 local function counter() n = n + 1 return n end return counter end c1 = new_counter() c2 = new_counter() print(c1()) -- 打印1 print(c2()) -- 打印1 print(c1()) -- 打印2 print(c2()) -- 打印2
Die Essenz von Abschlüssen kann auf das Umgebungsmodell in Kapitel 3 von verwiesen werden SICP. Hier können Sie sich einfach vorstellen, dass die Funktion counter ein privates Mitglied n hat.
Jetzt kommt die Frage: Ich möchte Python verwenden, um einen Abschluss mit derselben Funktion zu implementieren?
Schreiben Sie zunächst den Lua-Code direkt in Python-Code um:
def new_counter(): n = 0 def counter(): n = n + 1 return n return counter
Zeile 4 greift auf die nicht zugewiesene Variable n zu. Der Grund für den Fehler liegt nicht darin, dass Python keine Schließungen unterstützt, sondern darin, dass die Zuweisungsoperation von Python nicht auf die Variable n der oberen Ebene zugreifen kann (tatsächlich betrachtet Python sie als Definition lokaler Variablen und nicht als Zuweisung). Lokale Variablen definieren und Zuweisungsoperationen in Python sind syntaktisch widersprüchlich, Python unterstützt einfach nur neu definierbare Definitionsanweisungen. Da der Standardbereich von Python lokal ist, geht Python davon aus, dass es sich um eine Variablendefinitionsoperation handelt, wenn das Programm bei n = n 1 ausgeführt wird. Daher erstellt es eine (nicht initialisierte) lokale Variable n – und überschreibt erfolgreich new_counter. Eine Ebene von n – und versucht es dann Weisen Sie n 1 zu, aber n ist nicht initialisiert, n 1 kann nicht berechnet werden, daher meldet das Programm einen Fehler.
Mit einem kleinen Trick können Sie die Funktion der Abschlusszuweisung umsetzen:def new_counter(): n = [0] def counter(): n[0] = n[0] + 1 return n[0] return counter
Hier Der Grund, warum n[0] = n[0] 1 nicht schief geht, ist, dass das Gleichheitszeichen hier eine andere Bedeutung hat als das Gleichheitszeichen in n = n 1 zuvor. n[0] = n[0] Das Gleichheitszeichen in 1 bedeutet, ein Attribut von n zu ändern. Tatsächlich ruft dieses Gleichheitszeichen letztendlich die Methode __setitem__ der Liste auf. Das Gleichheitszeichen in n = n 1 bedeutet, den Wert n 1 an das Symbol n in der aktuellen Umgebung zu binden (wenn Symbol n bereits in der aktuellen Umgebung vorhanden ist, überschreiben Sie es).
Noch ein Exkurs: Verdammt, ich muss es nicht so schreiben, es ist so hässlich. Wie auch immer, Python ist eine objektorientierte Sprache. Um einen Zähler zu implementieren, können Sie genauso gut eine Klasse schreiben.
Trennung von Definition und Zuweisung
Lassen Sie uns zunächst die Merkmale des Standardbereichs von Python und Lua zusammenfassen:
1. Der Standardbereich von Lua ist global Wenn Sie ein Programm schreiben, müssen Sie sich das Schlüsselwort local merken (es sei denn, Sie müssen wirklich eine globale Variable definieren, Sie werden nicht dazu aufgefordert, sondern warten einfach, bis der Fehler behoben ist).
2. Der Standardbereich von Python ist lokal, obwohl die mentale Belastung beim Schreiben eines Programms geringer ist, es verliert die Fähigkeit, Variablen auf höherer Ebene Werte zuzuweisen (dies kann jedoch geändert werden). Sprache verwirrender).
Es scheint, dass beide Standardbereiche Probleme haben? Persönlich denke ich, dass der Grund für die oben genannten Probleme darin liegt, dass Python und Lua die Trennung von Definition und Zuweisung nicht erkennen. In Python und Lua kann eine Anweisung wie x = 1 entweder eine Definition oder eine Zuweisung darstellen. Tatsächlich erkennen nicht nur diese beiden Sprachen, sondern auch viele Hochsprachen die Trennung von Definition und Zuweisung nicht. Definition und Zuordnung sind in ihrer Funktion ähnlich, unterscheiden sich jedoch im Wesentlichen.
Im Folgenden wird x = 1 als Beispiel verwendet, um die Definition und Zuweisung zu erläutern:
Die Definition bedeutet: Registrieren Sie das Symbol x in der aktuellen Umgebung und initialisieren Sie es auf 1. Wenn x bereits existiert, wird ein Fehler gemeldet (Neudefinition ist nicht erlaubt) oder überschrieben (Neudefinition ist erlaubt).
Zuweisung bedeutet: Ausgehend von der aktuellen Umgebung Schicht für Schicht nach oben suchen, bis das Symbol x zum ersten Mal gefunden wird, und seinen Wert auf 1 ändern. Wenn sie nicht gefunden werden kann, wird ein Fehler gemeldet (die Variable existiert nicht).
Jetzt modifizieren wir Python leicht, um die Trennung von Definition und Zuweisung zu erreichen: Verwenden Sie „:=", um die Definition anzugeben, und „=", um die Zuweisung anzuzeigen. Schreiben Sie dann das new_counter-Beispiel neu, das nicht ausgeführt werden kann (die Zuweisungsoperation in Python steht in Konflikt mit der Definition lokaler Variablen. Mit anderen Worten, Python verfügt tatsächlich über keine Zuweisungsoperation, daher müssen wir einfach alle „=“ durch „:="“ ersetzen. ) , sehen Sie, wo es falsch ist:
def new_counter(): n := 0 def counter(): n := n + 1 return n return counter
Es ist offensichtlich, warum dieses Programm falsch ist. Was wir in Zeile 4 wollen, ist eine Zuweisungsoperation, keine Definitionsoperation. Ändern Sie es in die richtige Schreibweise:
def new_counter(): n := 0 def counter(): n = n + 1 return n return counter
Auf diese Weise wird es korrekt ausgeführt (vorausgesetzt, es gibt eine modifizierte Version des Python-Interpreters XD).
Lassen Sie uns zum Schluss noch über Lua sprechen. Lua hat das Gefühl, dass die Trennung von Definition und Zuweisung bereits zur Hälfte geschafft ist. Die Gleichheitszeichenanweisung mit dem lokalen Schlüsselwort muss definiert werden. Das Problem ist die Gleichheitszeichenanweisung ohne lokale. Für diese Art von Anweisung geht Lua folgendermaßen vor: Versuchen Sie zunächst, die Zuweisung durchzuführen. Wenn die Zuweisung fehlschlägt (die Variable existiert nicht), definieren Sie die Variable in der äußersten Umgebung (globale Umgebung). Mit anderen Worten: Die Gleichheitszeichenanweisung ohne lokale Vermischung von Definition und Zuweisung. Wenn außerdem die Trennung von Definition und Zuweisung erreicht wird, besteht keine Notwendigkeit, die Frage des Standardbereichs zu berücksichtigen – alle Definitionen werden in der aktuellen Umgebung definiert und alle definieren lokale Variablen. Ich kann mir wirklich keinen Vorteil vorstellen, wenn man globale Variablen in einem Funktionskörper oder einem anderen Block definiert.