Они различаются, потому что значение i
как в выражении генератора, так и в списке comp вычисляется лениво, т.е. когда анонимные функции вызываются в f
.
К этому времени i
привязывается к последнему значению, если t
, что равно -1.
Таким образом, в основном, это то, что делает понимание списка (аналогично для genexp):
x = []
i = 1 # 1. from t
x.append(lambda: i)
i = -1 # 2. from t
x.append(lambda: i)
Теперь лямбды содержат закрытие, которое ссылается на i
, но i
в обоих случаях связано с -1, потому что это последнее значение, которое ему было присвоено.
Если вы хотите убедиться, что лямбда получает текущее значение i
, выполните
f(*[lambda u=i: u for i in t])
Таким образом, вы форсируете оценку i
во время создания закрытия.
Редактировать : Существует одно различие между выражениями генератора и списками: последние пропускают переменную цикла в окружающую область.