2016-04-23 15 views
16

ich den folgenden Code in Python versucht 3.5.1:Wörterbuch Verständnis mit Lambda-Funktionen gibt falsche Ergebnisse

>>> f = {x: (lambda y: x) for x in range(10)} 
>>> f[5](3) 
9 

Es ist offensichtlich, dass diese 5 zurückkehren. Ich verstehe nicht, woher der andere Wert kommt, und ich konnte nichts finden.

Es scheint, als ob es sich um etwas handelt, das sich auf Referenz bezieht - es gibt immer die Antwort f[9] zurück, die die letzte zugewiesene Funktion ist.

Was ist der Fehler hier, und wie sollte dies geschehen, damit es richtig funktioniert?

Antwort

14

Python-Scoping ist lexikalisch. Eine Schließung bezieht sich auf den Namen und den Umfang der Variablen, nicht auf das tatsächliche Objekt/den Wert der Variablen.

Was passiert, ist, dass jedes Lambda die Variable xnicht den Wert von x aufzeichnet.

Am Ende der Schleife die Variable x-9 gebunden ist, daher jeder Lambda dieser x, dessen Wert 9.

Warum @ ChrisP Antwort funktioniert beziehen:

make_func erzwingt die Auswertung des Werts x (wie er in eine Funktion übergeben wird). Daher wird das Lambda mit dem Wert x zur Zeit erstellt, und wir vermeiden das obige Problem mit dem Geltungsbereich.

def make_func(x): 
    return lambda y: x 

f = {x: make_func(x) for x in range(10)} 
+7

Eine alternative Kurzschrift würde 'f = {x: (lambda y, x = x: x) für x im Bereich (10)}', weil Funktion Standardargumente zur Definitionszeit gebunden, so Sie würden den _value_ von 'x' binden, nicht den _name_' x'. – ShadowRanger

+0

Das hört sich vielleicht nach einer sehr dummen Frage an (ich kenne Lambda nicht allzu gut), aber wie funktioniert make_func (x)? Ich kann mir vorstellen, dass f [5] (3) bedeutet -> f = {5: make_func (5)}. Wie ist es also, dass make_func (5) (3) gleich 5 ist? – Adib

+1

Das Wörterbuch Verständnis macht ein Wörterbuch Schlüssel von Ints zu Werten von Funktionen. f [5] gibt den Wert im Wörterbuch zurück, der mit 5 codiert ist. Dies ist die Funktion Lambda y: x. Beachten Sie, dass das Lambda ignoriert, was übergeben wird (y) und immer x zurückgibt. Deshalb wird das Lambda entweder 5 oder 9 zurückgeben (aufgrund des oben beschriebenen Problems). – gnicholas

6

sollten folgende Arbeiten:

def make_func(x): 
    return lambda y: x 

f = {x: make_func(x) for x in range(10)} 

Die x in Ihrem Code endet mit dem letzten x Wert Bezug auf, die 9, aber in mir ist es bezieht sich auf die x im Funktionsumfang.

Verwandte Themen