[python] Привязка переменных в list displays
От: Roman Odaisky Украина  
Дата: 23.11.09 21:55
Оценка:
Требуется создать несколько лямбда-функций внутри выражения list display (оно же list comprehension). Это нужно для DeferredList в Twisted. Пишу примерно так:
return defer.DeferredList([
   make_deferred_somehow(j).addCallback(
       lambda x: perform_postprocessing(x, i) # это i должно быть каждый раз разным
   )
   for i, j in get_some_data()
])

Однако получается невесть что — все лямбда-выражения ссылаются на одно и то же значение i. Минимальный пример:
>>> constant = lambda x: lambda: x
>>> [f() for f in [constant(i) for i in range(5)]]
[0, 1, 2, 3, 4] # ожидаемое поведение
>>> [f() for f in [(lambda: i) for i in range(5)]]
[4, 4, 4, 4, 4] # почему все λ привязались к одной и той же i?!

И даже так:
>>> fs = ((lambda: i) for i in range(5))
>>> f0 = next(fs)
>>> f1 = next(fs)
>>> f0()
1
>>> f1()
1
>>> f2 = next(fs)
>>> f0()
2
>>> f1()
2

Пока нашел только один workaround:
>>> [f() for f in [(lambda i=i: i) for i in range(5)]]
[0, 1, 2, 3, 4]

А как сделать по-человечески?
До последнего не верил в пирамиду Лебедева.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.