Seite 1 von 1

Lambda-Funktion als Atribut einer Klasse

Verfasst: Donnerstag 4. April 2013, 20:06
von calo
Hallo,

Ich möchte eine Lambda-Funktion mit verschiedenen Koeffizienten als Attribut einer Klasse abspeichern. Leider will das nicht so recht klappen. Kann mir da einer weiterhelfen?

Folgender Code:

Code: Alles auswählen

a = {23: (6622.3889855338457, 3.4964973502475862, 29.741146883501557),
     40: (5778.1500751826816, 2.7106131510817519, 32.674306382093654),
     60: (5298.5603201219001, 2.3384280000649538, 36.757223997745143)}

class Test(object):
    def __init__(self):
        self.fitfunc = {}

    def def_func(self):
        for T in a.keys():
            p = a[T]
            self.fitfunc[T] = lambda x: p[0]*x * ((1 - p[1]*x) / (1 + p[2]*x))
            print self.fitfunc[T](0.0005),
        print

b = Test()
b.def_func()
for T in (23, 40, 60):
    print b.fitfunc[T](0.0005),
Ausgabe ist dann:

Code: Alles auswählen

2.83878184138 2.59842710111 3.25697265039
3.25697265039 3.25697265039 3.25697265039
Die 1. Zeile gibt das korrekte Ergebnis wider. In der 2. Zeile würde ich das gleich erwarten. Es wird aber immer nur das Ergebnis für T=23 ausgegeben. Warum :? :?:

Calo

Re: Lambda-Funktion als Atribut einer Klasse

Verfasst: Donnerstag 4. April 2013, 20:16
von Sirius3
Hallo calo,

die Variable b ist im Namensraum der lambda-Funktion nicht definiert, also wird sie aus dem ihr übergeordneten Namensraum, der Funktion def_func genommen, dort ändert sich der Wert von p bei jedem Schleifendurchgang. Alle lambda-Funktionen besitzen also das gleiche p.
Als kleine Demonstration:

Code: Alles auswählen

>>> def get_func(a):
...   result = lambda: a
...   a*=2
...   return result
... 
>>> x=get_func(8)
>>> x()
16
Hier wird a innerhalb von get_func, aber nach dem Erzeugen der lambda-Funktion geändert.

Re: Lambda-Funktion als Atribut einer Klasse

Verfasst: Donnerstag 4. April 2013, 20:16
von BlackJack
@calo: Weil das `p` erst aufgelöst wird wenn die ``lambda``-Funktion ausgeführt wird, und zu *dem* Zeitpunkt ist `p` an den Wert gebunden, den es im letzten Schleifendurchlauf zugewiesen, bekommt wenn man es *nach* der Schleife aufruft.

Lösungsmöglichkeit: eine ``lambda``-Funktion die nicht nur `x` sondern auch `p` übergeben bekommt und das dann zum Beispiel als Default-Wert binden:

Code: Alles auswählen

    def def_func(self):
        for p, T in a.iteritems():
            self.fitfunc[T] = lambda x, p=p: p[0]*x * ((1 - p[1]*x) / (1 + p[2]*x))
            print self.fitfunc[T](0.0005),
        print

Re: Lambda-Funktion als Atribut einer Klasse

Verfasst: Donnerstag 4. April 2013, 20:25
von Sirius3
oder das Benutzen einer weiteren Funktion, die p an den aktuellen Wert bindet:

Code: Alles auswählen

def def_func(self):
        for T, p in a.iteritems():
            self.fitfunc[T] = (lambda p: lambda x: p[0]*x * ((1 - p[1]*x) / (1 + p[2]*x)))(p)
            print self.fitfunc[T](0.0005),
        print

Re: Lambda-Funktion als Atribut einer Klasse

Verfasst: Donnerstag 4. April 2013, 21:06
von calo
Hi, super. Vielen Dank ... jetzt funktionierts :lol: