Seite 1 von 1

Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 09:09
von IoI
Hallo,

ich muss zur Laufzeit ein paar Funktionen generieren, die nachher an andere Stelle wichtig sind. Die Funktionen werden in einer Schleife definiert und an eine List angehängt.

Mein Problem besteht jetzt darin, dass immer nur die Werte aus dem letzten Schleifendurchgang in alle generierten Funktionen eingesetzt werden.

Hier ein vereinfachtes Beispiel:

Code: Alles auswählen

for i in range(3):
  fn.append(lambda x: i*x)

for func in fn:
  for j in range(5):
    print func(j),
  print

"""
Ausgabe:
0 2 4 6 8
0 2 4 6 8
0 2 4 6 8
"""

fn = list()

for i in range(3):
  def curFunc(x):
    return x*i
  fn.append(curFunc)

for func in fn:
  for j in range(5):
    print func(j),
  print

"""
Ausgabe:
0 2 4 6 8
0 2 4 6 8
0 2 4 6 8
"""

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 09:18
von ms4py
IoI hat geschrieben: Mein Problem besteht jetzt darin, dass immer nur die Werte aus dem letzten Schleifendurchgang in alle generierten Funktionen eingesetzt werden.
So ist eben der Scope einer lambda-Funktion definiert. Leider etwas magic...
Wenn du uns dein eigentliches Vorhaben erläuterst, können wir dir bestimmt eine gute Alternative vorschlagen.

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 09:29
von IoI
Ich habe in der Schleife verschiedene sympy Funktionen z.B. func = -5*y+3*x*y+x**2 und will jetzt eine Funktion zurück geben in der nachher x und y eingesetzt werden können also lambda wertx,werty: float(func.subs({'x':wertx, 'y':werty}))

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 09:43
von Hyperion
Wenn ich das richtig verstehe mach 's doch so:

Code: Alles auswählen

def eval_func(func, **kwargs)
    return float(func.subs(kwargs))

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 09:46
von IoI
Hyperion hat geschrieben:Wenn ich das richtig verstehe mach 's doch so:

Code: Alles auswählen

def eval_func(func, **kwargs)
    return float(func.subs(kwargs))
func ändert sich aber auch mit jeder Schleife.

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 09:49
von BlackJack
@IoI: Das `i` wird zur Zeit des *Aufrufs* zu einem Wert aufgelöst und nicht zu dem Zeitpunkt an dem die Funktion, ob nun mit ``lambda`` oder mit ``def``, definiert wird.

Lösung: Das in der Funktion lokal binden, zum Beispiel über ein Default-Argument. Das wird nämlich bei der Definition der Funktion ausgewertet:

Code: Alles auswählen

lambda x, i=i: i*x
Alternativ mit `functools.partial()`:

Code: Alles auswählen

partial((lambda i, x: i*x), i)

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 10:03
von Hyperion
IoI hat geschrieben: func ändert sich aber auch mit jeder Schleife.
Wo kommen denn die Änderungen her? Ist das nur dieses "i"?

Letztlich könntest Du das "i" doch hier auch noch übergeben... oder eben mit partial arbeiten und diese Objekte dann in eine Liste packen, wie BlackJack es vorschlug.

Re: Funktionen in Schleife generieren

Verfasst: Montag 10. Mai 2010, 10:05
von IoI
Yeah, genau was ich gesucht habe, danke BlackJack.