Geschichte der Frage:
In Perl kann der Geltungsbereich von Variablen durch die Operatoren my (lexikale Sichtbarkeit) und local (dynamische temporäre Neuzuweisung) eingeschränkt werden. local wird häufig verwendet, um globale Variablen und spezielle Deskriptoren (Typ $_, $/, $@, %ENV) zu überschreiben.
Problem:
Das Hauptproblem ist die Verwirrung zwischen dynamischem und lexikalischem Scope. local erstellt keine neue Variable, sondern ersetzt vorübergehend den Wert in einer globalen (oder Package-)Variablen während der Ausführung des Blocks. Dies ist besonders kritisch beim Überschreiben von Variablen wie $/ (Zeilen-Trennzeichen), $_ (Standardvariable), $^W (Warnflag), %ENV, STDIN/STDOUT.
Lösung:
Beispielcode:
our $Global = "Hello!"; sub change1 { my $Global = "Bye!"; print "$Global "; } sub change2 { local $Global = "Bye!"; print "$Global "; } print "$Global "; # Hello! change1(); # Bye! print "$Global "; # Hello! change2(); # Bye! print "$Global "; # Hello!
Schlüsselfeatures:
Kann local auf lexikalische Variablen angewendet werden, die mit my deklariert wurden?
Nein, local funktioniert nur mit package-globalen Variablen. Bei my-Objekten ist es machtlos.
Was passiert, wenn local auf spezielle Deskriptoren, z.B. STDIN, angewendet wird?
Es ist möglich, STDIN/STDOUT/stdin temporär über local neu zuzuweisen, um zum Beispiel den Eingabe-/Ausgabestrom in einer Unterprogramm ohne globalen Effekt zu ersetzen. Nach dem Verlassen des Blocks wird der Handle wiederhergestellt.
Was ist der kritische Unterschied zwischen local und my bei rekursiven Funktionsaufrufen?
local sorgt für einen "push/pop"-Stack von Werten – jeder Aufruf überschreibt vorübergehend den Wert des Pakets, und verschachtelte Aufrufe erhalten diesen überschriebenen Wert. my bietet einen einzigen lexikalischen Wert innerhalb des Blocks ohne Vererbung nach innen.
Im Test wird local verwendet, um %ENV zu überschreiben, nach dem Verlassen des Blocks unerwartete Nebenwirkungen in anderen Threads, weil der Code mehrthreadig ist und local nicht ordnungsgemäß verwendet wurde.
Vorteile:
Nachteile:
Besondere Variablen ($/, $@, $SIG) werden nur für die Dauer des benötigten Blocks überschrieben, anschließend werden die Änderungen korrekt zurückgesetzt.
Vorteile:
Nachteile: