Привязать локальную переменную к вложенной функции в python [duplicate]

{{ ['foo', 'bar'|capitalize]|join }}

Как вы можете видеть, это работает с фильтрами и функциями без необходимости использовать set на отдельной строке.

38
задан Shep 4 May 2012 в 22:58
поделиться

2 ответа

Измените x.append(lambda : pv(v)) на x.append(lambda v=v: pv(v)).

Вы ожидаете, что «python lambdas привязывается к ссылке, на которую указывает локальная переменная, за сценой», но это не так, как работает Python. Python ищет имя переменной во время вызова функции, а не когда она создается. Использование аргумента по умолчанию работает, потому что аргументы по умолчанию оцениваются при создании функции, а не при ее вызове.

Это не что-то особенное в отношении лямбда. Рассмотрим:

x = "before foo defined"
def foo():
    print x
x = "after foo was defined"
foo()

печатает

after foo was defined
68
ответ дан Steven Rumbalski 20 August 2018 в 16:11
поделиться
  • 1
    интересно, не могли бы вы подробно рассказать об интуиции механики. – Hassan Syed 4 May 2012 в 17:38
  • 2
    Более очевидной альтернативой является использование functools.partial или использование отдельной вспомогательной функции для создания замыканий (def make_closure(v): return lambda: pv(v), вы можете поместить ее в test). – user 4 May 2012 в 17:40
  • 3
    поэтому мой реальный код должен понравиться lambda par1, par2 = l3_e : self.parse_l4(par1, par2)? – Hassan Syed 4 May 2012 в 17:46
  • 4
    Если v сам по себе является ссылкой (в отличие от int), тогда я беру его, то будет not быть «глубоким». копировать? – Aaron McDaid 4 March 2014 в 16:30

Закрытие лямбды содержит ссылку на используемую переменную, а не ее значение, поэтому, если значение переменной позже изменяется, значение в закрытии также изменяется. То есть значение переменной замыкания разрешается при вызове функции, а не при ее создании. (Поведение Python здесь не является чем-то необычным в мире функционального программирования, для чего оно стоит.)

Существует два решения:

  1. Используйте аргумент по умолчанию, привязывая текущее значение от переменной до локального имени во время определения. lambda v=v: pv(v)
  2. Используйте двойную лямбда и немедленно вызывайте первый. (lambda v: lambda: pv(v))(v)
14
ответ дан kindall 20 August 2018 в 16:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: