2017-02-02 10 views
12

Chcę napisać funkcję, która zwraca listę funkcji. Jako MWE, oto moja próba funkcji, która daje trzy funkcje, które dodają 0, 1 i 2 do liczby wejściowych:Jak mogę zwrócić funkcję korzystającą z wartości zmiennej?

def foo(): 
    result = [] 
    for i in range(3): 
     temp = lambda x: x + i 
     print(temp(42)) # prints 42, 43, 44 
     result.append(temp) 
    return result 

for f in foo(): 
    print(f(42)) #prints 44, 44, 44 

Wbrew moim oczekiwaniom, każda funkcja kończy się stosując ostatnią wartość podjętą przez ja. Podobne zachowanie zaobserwowałem, gdy np. lista jest używana jako argument do funkcji, ale Python faktycznie używa wskaźnika do listy, ale tutaj jest liczbą całkowitą, więc nie rozumiem co tu się dzieje. Używam Pythona 3.5.

Odpowiedz

14

Zamknięcia wiążą późne, co oznacza, będą korzystać z ostatnią wartość i w zakresie zostały one zdefiniowane po nazwie (w tym przypadku ostatnia wartość i będzie 2).

Wspólna Rozwiązaniem tego problemu jest zapewnienie wartości i jako domyślnej argumentu:

temp = lambda x, i=i: x + i 

Od Python ocenia domyślne argumenty podczas budowy funkcji, jest to trik, który pomaga Python używać poprawnej wartości i, gdy wywoływany jest wywoływany, nie tworzy zamknięcia, a zamiast tego może wyglądać na i w swoich lokalnych.

+2

Więcej informacji na temat tej odpowiedzi http://quickinsights.io/python/python-closures-and-late-binding/ –

+0

Dzięki! Żeby w 100% upewnić się, że rozumiem - przez to rozumiesz, że wartość użyta dla wszystkich i jest wartością i, gdy kod wychodzi poza zakres definicji funkcji? – ahura

+1

Wolę używać 'functools.partial' zamiast przypisywania domyślnych argumentów, wydaje się być czystsze. –

Powiązane problemy