2011-09-25 28 views
20

Powiel możliwe:
What do (lambda) function closures capture in Python?
lambda function don't closure the parameter in Python?Tworzenie lambda wewnątrz pętli

próbuję tworzyć lambdy wewnątrz pętli, która wykonuje iteracje nad listą obiektów:

lambdas_list = [] 
for obj in obj_list: 
    lambdas_list.append(lambda : obj.some_var) 

Teraz, jeśli przejdę przez lambdas listę i wywołaj je w ten sposób:

for f in lambdas_list: 
    print f() 

Otrzymuję tę samą wartość. Jest to wartość ostatniego obj w obj_list, ponieważ była to ostatnia zmienna w bloku iteratora listy. Jakieś pomysły na dobre (pythonic) przepisanie kodu, aby działało?

+1

patrz http://stackoverflow.com/questions/2295290/what-do-lambda-function-closure-capture-in-python/2295372#2295372 i http://stackoverflow.com/questions/7514093/lambda -funkcja-dont-zamknięcie-parametr-w-python. –

+0

Najbardziej opisowa odpowiedź: http://stackoverflow.com/questions/938429/scope-of-python-lambda-functions-and-their-parameters/938493#938493 –

Odpowiedz

22

Użyj tej linii zamiast:

lambdas_list.append(lambda obj=obj: obj.some_var) 
+0

Bardziej elegancki niż użycie częściowego. – zoujyjs

4

można zrobić coś takiego:

def build_lambda(obj): 
    return lambda : obj.some_var 

lambdas_list = [] 
for obj in obj_list: 
    lambdas_list.append(build_lambda(obj)) 
8

albo trzeba uchwycić zmienną użyciu domyślnych przypisań

lambdas_list = [ lambda i=o: i.some_var for o in obj_list ] 

o r, zamknięć mechanicznych uchwycić zmienna

lambdas_list = [ (lambda a: lambda: a.some_var)(o) for o in obj_list ] 

w obu przypadkach kluczowe jest, aby upewnić się, że każda wartość w liście obj_list jest przypisany unikalny zakres.

Twoje rozwiązanie nie działa, ponieważ zmienna leksykalna obj odwołuje się do zakresu nadrzędnego (for).

Domyślne przypisanie działało, ponieważ odwołujemy się do i z zakresu lambda. Używamy domyślnego przypisania, aby "przekazać" zmienną niejawnie, czyniąc ją częścią definicji lambda, a zatem jej zakresem.

Rozwiązanie zamknięcia działa, ponieważ zmienna "przekazywanie" jest jawna, w zewnętrznym lambda, która jest natychmiast wykonywana, tworząc w ten sposób powiązanie podczas rozumienia listy i zwracając wewnętrzną wartość lambda, która odwołuje się do tego wiązania. Tak więc, gdy wewnętrznie wykonuje się wewnętrzne, to będzie odwoływać się do powiązania utworzonego w zewnętrznym zakresie lambda.