Подтвердить что ты не робот

Создание лямбда внутри цикла

Возможный дубликат:
Что делает захват функции лямбда-функции в Python?
лямбда-функция не закрывает параметр в Python?

Я пытаюсь создать lambdas внутри цикла, который выполняет итерацию над списком объектов:

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

Теперь, если я перебираю список lambdas и вызываю их следующим образом:

for f in lambdas_list:
    print f()

Я получаю то же значение. Это значение последнего obj в obj_list, так как это была последняя переменная в блоке итератора списка. Любые идеи fn хорошего (питонова) переписывают код, чтобы заставить его работать?

4b9b3361

Ответ 1

Используйте эту строку вместо:

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

Ответ 2

Вам нужно либо захватить переменную, используя назначения по умолчанию

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

или используйте закрытие для захвата переменной

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

В обоих случаях ключ должен удостовериться, что каждому значению в списке obj_list присваивается уникальная область.

Ваше решение не работает, потому что лексическая переменная obj ссылается на родительскую область (for).

Работа по умолчанию работала, потому что мы ссылаемся на i из области lambda. Мы используем назначение по умолчанию, чтобы сделать "передачу" переменной неявной, сделав ее частью определения lambda и, следовательно, ее областью.

Решение замыкания работает, потому что переменная "передача" является явной, во внешнюю lambda, которая немедленно выполняется, тем самым создавая привязку во время понимания списка и возвращая внутренний lambda, который ссылается на эту привязку. Поэтому, когда на самом деле выполняется внутренний lambda, он будет ссылаться на привязку, созданную во внешней области lambda.

Ответ 3

Вы можете сделать что-то вроде этого:

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

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