Automatische Bindung von Bereichsvariablen in einer Schließung

Betrachten Sie diesen (ziemlich sinnlosen) Javascript-Code:

function make_closure() { var x = 123, y = 456; return function(varname) { return eval(varname) } } closure = make_closure() closure("x") // 123 closure("y") // 456 

Die von make_closure Funktion enthält keine Verweise auf Bereichsvariablen, kann aber trotzdem ihre Werte zurückgeben, wenn sie aufgerufen werden.

Gibt es einen Weg, das gleiche in Python zu tun?

 def make_closure(): x = 123 return lambda varname: ...no "x" here... closure = make_closure() print closure("x") # 123 

Mit anderen Worten, wie man eine Schließung schreibt, die "über" Variablen in der Definition von Umfang "wissen würde, ohne sie explizit zu erwähnen?

  • Wie verstehe ich die Schließung in einem Lambda?
  • Dynamische Aufruf von verschachtelten Funktionen basierend auf Argumenten
  • Pythongeneratoren mit Verschlüssen umsetzen
  • Lokaler Umfang, über den Umfang der Umschließung hinaus
  • Was macht die Lambda-Funktion?
  • Wie funktionieren geschachtelte Funktionen in Python?
  • Pythonverschluss funktioniert nicht wie erwartet
  • Pythonverschlüsse und Zellen (geschlossene Werte)
  • 4 Solutions collect form web for “Automatische Bindung von Bereichsvariablen in einer Schließung”

    Das ist wahrscheinlich das genaueste zu einem exakten äquivalent:

     def make_closure(): x = 123 l = locals() return lambda(varname): eval(varname, None, l) closure = make_closure() print closure("x") # 123 

    Letztlich ist dein Problem nicht, dass x nicht von deiner örtlichen Schließung erfasst wurde, sondern dass dein lokaler Bereich nicht in eval übergeben wurde.

    Weitere Informationen zur eval-Funktion finden Sie unter http://docs.python.org/library/functions.html#eval .

    Es versteht sich vermutlich, dass dies nicht eine sehr pythonische Sache ist. Sie wollen fast nie wirklich in Python anrufen! Wenn du denkst, dass du tust, schritt zurück und überdenke dein größeres Design. Aber wenn du es gebrauchen musst, musst du verstehen, wie es anders ist als Javascript eval. Es ist letztlich leistungsfähiger – es kann verwendet werden, um dynamisches Scoping zu simulieren, oder als eine vereinfachte Version von exec, oder um Code in jeder beliebig konstruierten Umgebung zu bewerten – aber das bedeutet auch, dass es schwieriger ist.

    Die Leute haben bereits mit locals() . Ein anderer, zugegebenermaßen weniger flexibler Ansatz ist, das neue nonlocal Schlüsselwort in Python 3 zu verwenden:

     >>> def make_closure(): ... x = 123 ... def return_var(varname): ... nonlocal x ... return eval(varname) ... return return_var ... >>> closure = make_closure() >>> closure("x") 123 

    Dies hat den offensichtlichen Nachteil, dass Sie die Variablen aus dem äußeren Bereich, die Sie schließen möchten, explizit beschriften und verweisen.

    Du kannst etwa Variablen in Python schließen, etwa wie du in Javascript:

     def foo(): x = 123 return lambda y: x+y q = foo() print q(5) 

    http://ideone.com/Q8iBg

    Allerdings gibt es einige Unterschiede – zum Beispiel können Sie nicht schreiben, um Variablen in den Elternbereich (versuchen zu schreiben nur erstellt eine lokal-scoped Variable statt). Auch Python's eval() enthält keine Elternteile.

    Sie können dies für eval() umgehen, indem Sie die Einheimischen ausdrücklich von den Elternteilen erobern und sie in das eval() des eval() , aber die eigentliche Frage hier ist, warum müssen Sie das tun?

    In Python 2.x das erfordert einige massive kludging. In Python 3.x wurde jedoch das 'nonlocal'-Schlüsselwort eingeführt, um den Zugriff auf Variablen im unmittelbar umschließenden Bereich zu ermöglichen.

    Vielleicht lohnt es sich hier zu überprüfen, um weitere Informationen zu erhalten: nonlocal keyword in Python 2.x

    Python ist die beste Programmiersprache der Welt.