При захвате переменной в определении лямбды исходная переменная, похоже, сохраняется.
Поскольку вы сделали это значением по умолчанию для аргумента test
лямбды, иPython оценивает аргументы по умолчанию только один раз при создании функции.Кстати, это не имеет ничего общего с использованием ключевого слова lambda
- lambda
- это просто синтаксический сахар, и вы получите точно такой же результат с полнофункциональной функцией, то есть:
test = 123
def f(x, test=test):
print(x, test)
test = 456
f('hello')
Можно ли использовать лямбду, если вы также можете использовать простой объект для хранения тех же данных?
Апельсины и яблоки, правда.Функция предназначена не для «хранения» чего-либо, а для выполнения некоторых вычислений.Тот факт, что он может захватывать некоторые значения либо через аргументы по умолчанию, либо через замыкание, хотя и весьма полезен для некоторых случаев использования, не означает замену для надлежащих объектов или коллекций.Таким образом, ответ: зависит от того, что вы хотите сделать с этими значениями и вашей функции.
Примечание: технически, то, что вы здесь делаете, это (почти) то, что известно как «частичное приложение» (вам просто нужно переименовать Test.f
в Test.__call__
и использовать t("hello")
во второмпример)).Частичное применение функции - это механизм, с помощью которого функция из N аргументов, когда вызывается с N - x (с x
def foo(a, b=None):
if b is None:
return lambda b, a=a: foo(b, a)
return a + b
# here, `f` is a partial application of function `foo` to `1`
f = foo(1)
print(f)
f(2)
В этом случае мы используем замыкание для захвата a
, в традиции функционального программирования - «частичное применение» также в основном является концепцией функционального программирования FWIW.Теперь, хотя он поддерживает некоторые функции и идиомы FP, Python в первую очередь является языком OO, и поскольку замыкания являются эквивалентом объектов FP (замыкания являются способом инкапсуляции состояния и поведения вместе), также имеет смысл реализовать частичное применениекак соответствующий класс, либо со специализированными объектами "ad hoc" (ваш Test
класс, но также Method
объекты), либо с более общим "частичным" классом - , который уже существует в stdlib как functools.partial