Lambda-Funktion acessing außerhalb variabel [duplicate]

Diese Frage hat hier schon eine Antwort:

  • Was macht die Lambda-Funktion? 6 antworten

Ich wollte mit anonymen Funktionen herumspielen, also habe ich beschlossen, einen einfachen Prime Finder zu machen. Hier ist es:

tests = [] end = int(1e2) i = 3 while i <= end: a = map(lambda f:f(i),tests) if True not in a: tests.append(lambda x:x%i==0) print i print tests print "Test: "+str(i) print str(a) i+=2 

Was ich aber finde, ist, dass das i in der lambda x:x%i==0 jedes Mal zugegriffen wird, während ich es will, dass es eine wörtliche Zahl ist. Wie bekomme ich es zu lambda x:x%3==0 statt?

3 Solutions collect form web for “Lambda-Funktion acessing außerhalb variabel [duplicate]”

Du kannst das bei der Erstellung des Lambda "erfassen"

 lambda x, i=i: x%i==0 

Dies wird das i in den Lambda-Kontext gleich, was i war, wenn es erstellt wurde. Du könntest auch sagen, lambda x, n=i: x%n==0 wenn du wolltest, es ist nicht genau Capture, aber es bekommt dich was du brauchst

Ohne das, wie du gesehen hast, wird es nach einem i im umschließenden Bereich suchen


Es ist eine Frage der Suche, die analog zu den folgenden mit definierten Funktionen ist:

 i = "original" def print_i1(): print(i) # prints "changed" when called below def print_i2(s=i): #default set at function creation, not call print(s) # prints "original" when called below i = "changed" print_i1() print_i2() 

Das Problem ist, dass jede dieser Funktionen in tests sich auf die Variable i bezieht.

Häufiger wirst du dies in einer Funktion, in diesem Fall hast du eine lokal-to-the-defining-scope Variable i , die in einer Schließung gespeichert wird, wie schön in diesen Nasty Closures erklärt .

Aber hier ist es noch einfacher: i bin eine globale Variable, also gibt es keine Schließung. Die Funktionen werden kompiliert, um i als globale Variable beim Ausführen aufzusuchen. Da i mich geändert habe, sehen die Funktionen den geänderten Wert, wenn sie laufen. So einfach ist das.


Der traditionelle Weg um diese (was sowohl für Verschlüsse als auch für Globals funktioniert) ist lieblich als "der Standard-Wert-Hack" bekannt, obwohl es nicht wirklich ein Hack ist. (Siehe die Erklärung in der FAQ .) Ryan Hainings Antwort erklärt, wie dies zu tun ist:

 lambda x, i=i: x%i==0 

Dies erzeugt einen Parameter namens i , wobei ein Standardwert gleich dem Wert von i zum Zeitpunkt der Erstellung der Funktion ist. Dann, innerhalb der Funktion, wenn Sie auf den Parameter i zugreifen, und Sie erhalten diesen Wert.


Eine andere Art und Weise um diese, die vielleicht vertrauter erscheinen, wenn Sie in Sprachen wie JavaScript verwenden, ist es, eine Funktion-Erstellung-Funktion zu erstellen, und übergeben Sie den Wert von i als Argument für diese Funktion-Erstellung-Funktion, wie in user2864740 die Antwort :

 (lambda i: lambda x: x%i)(i) 

Dies vermeidet die "Verschmutzung" der Signatur der Funktion mit einem zusätzlichen Parameter (der jemand versehentlich ein Argument übergeben könnte), aber auf Kosten der Erstellung und Aufruf einer Funktion aus keinem guten Grund.


Ein dritter Weg um diese ist, partial zu benutzen. In Fällen, in denen alles, was Sie versuchen zu tun, ist teilweise eine Funktion anwenden, mit partial statt definieren eine Wrapper-Funktion als lambda kann sauberer sein.

Leider ist in diesem Fall die Funktion innerhalb eines Operators verborgen, und die Funktion operator.mod , die es aussetzt, nimmt keine Keyword-Argumente, so dass man seinen zweiten Operanden nicht sinnvoll partitionieren kann. Also, das ist eine schlechte Lösung in diesem Fall. Wenn du es wirklich wolltest, könntest du einfach einen Wrapper schreiben, der sich besser und partial verhält:

 def opmod(a, b): return a % b partial(operator.mod, b=i) 

In diesem Fall denke ich, du bist besser mit den anderen Lösungen! Halten Sie einfach diese in Ihren Kopf für Fälle, in denen es angebracht ist.

Erstellen Sie eine neue Funktion, die das Lambda zurückgibt. Dann rufe das an und gebe i als Argument ein. Dadurch wird ein neuer verbindlicher Rahmen geschaffen.

 def make_test (i): # this i refers to the parameter (which evaluates to the /value/ passed) return lambda x: x%i==0 # .. # the /value/ resulting from evaluating the variable is passed tests.append(make_test(i)) 
  • Den Block der Befehle, die in der mit Anweisung ausgeführt werden sollen
  • Globals und Einheimische in python exec ()
  • Warum ist der Ort zum Zeitpunkt der Kompilierung bestimmt?
  • Was bedeutet Umfang
  • Kurze Beschreibung der Scoping Regeln?
  • Warum verschachtelte Funktionen auf Variablen von äußeren Funktionen zugreifen können, aber sie nicht ändern dürfen [duplizieren]
  • Python: Variablen sind noch zugänglich, wenn in try oder if definiert?
  • Python eval (kompilieren (...), Sandkasten), Globals gehen in Sandbox, wenn nicht in def, warum?
  • Wie kann man neue Scopes in Python schaffen?
  • Blockieren Sie den Bereich in Python
  • String mit 'f' Präfix in python-3.6
  • Python ist die beste Programmiersprache der Welt.