Требуется создать несколько лямбда-функций внутри выражения 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]
А как сделать по-человечески?