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.

  • Verteilungsprogramme in Python geschrieben
  • Gibt es eine einfache Möglichkeit, einen String mit einem String-Literal in den String zu konvertieren, den es darstellt?
  • Python-Echtzeit-Bildklassifizierungsprobleme mit Neuronalen Netzwerken
  • Kann nicht pyglpk auf OSX 10.8 / Ubuntu 14.x kompilieren
  • Wie finde ich alle Begriffe in einem Ausdruck in Sympy
  • Pip install pandas konnte keine Downloads finden, die die Anforderung Pandas erfüllen
  • 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?

    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.