Das Problem ist, dass jede dieser Funktionen in tests
bezieht sich auf die Variable i
.
Üblicherweise machen Sie dies innerhalb einer Funktion, in diesem Fall haben Sie eine Variable i
, die in einem Abschluss gespeichert wird, wie in These Nasty Closures erklärt.
Aber hier ist es noch einfacher: i
ist eine globale Variable, also gibt es keine Schließung. Die Funktionen werden kompiliert, um i
als eine globale Variable zu suchen, wenn sie ausgeführt wird. Da sich i
geändert hat, sehen die Funktionen den geänderten Wert, wenn sie ausgeführt werden. So einfach ist das.
Der traditionelle Weg, um diese als „default-Wert Hack“ liebevoll genannt wird (die für beide Verschlüsse und Globals funktioniert), auch wenn es nicht wirklich ein Hack ist. (Siehe the explanation in the FAQ.) Ryan Haining Antwort erklärt, wie dies zu tun:
lambda x, i=i: x%i==0
Dies erzeugt einen Parameter i
, mit einem Standardwert gleich den Wert von i
zu der Zeit genannt die Funktion erstellt wird. Dann innerhalb der Funktion, wenn Sie auf Parameter i
zugreifen, und Sie erhalten diesen Wert.
Eine andere Möglichkeit, um dieses, die besser vertraut zu sein scheint, wenn Sie Sprachen wie JavaScript verwenden sind, ist eine Funktion schöpf Funktion, zu erstellen und den Wert von i
als Argument an, dass funktions- übergeben Funktion zu schaffen, wie es in user2864740 Antwort:
(lambda i: lambda x: x%i)(i)
Dies vermeidet die Signatur der Funktion mit einem zusätzlichen Parameter „verschmutzen“, aber auf Kosten der Erstellung und den Aufruf einer Funktion (dass jemand aus Versehen ein Argument passieren könnte) aus keinem guten Grund.
Ein dritter Weg ist partial
zu verwenden. In Fällen, in denen Sie nur versuchen, eine Funktion teilweise anzuwenden, verwenden partial
anstatt eine Wrapper-Funktion als lambda
definieren kann sauberer sein.
Leider ist in diesem Fall die Funktion in einem Operator verborgen, und die Funktion operator.mod
, die es verfügbar macht, nimmt keine Schlüsselwortargumente, so dass Sie seinen zweiten Operanden nicht sinnvoll partiell verwenden können. Also, das ist in diesem Fall eine schlechte Lösung. Wenn Sie wirklich wollte, könnte man nur einen Wrapper schreiben, die besser und partial
verhält sich das:
def opmod(a, b):
return a % b
partial(operator.mod, b=i)
In diesem Fall, ich glaube, du bist besser mit den anderen Lösungen aus; behalte es einfach in deinem Kopf für Fälle, in denen es geeignet ist.
Siehe auch [Diese Nasty Closures] (http://code.activestate.com/recipes/502271/) für eine bessere Erklärung als die in der offiziellen Dokumentation. Aber die kurze Version ist, dass jede dieser Testfunktionen effektiv eine Schließung um die gleiche Variable "i" ist und "i" den Wert ständig ändert. (Dies ist nicht ganz korrekt, weil globale Variablen nicht wirklich in Schließungen gespeichert werden müssen, aber der Effekt ist der gleiche.) – abarnert