Python лямбда-захват внешних переменных - PullRequest
0 голосов
/ 08 октября 2018

Рассмотрим следующий пример:

test = 123
f = lambda x,test=test: print(x, test)
del test
f('hello')

print

hello 123

При захвате переменной в лямбда-определении исходная переменная, похоже, сохраняется.

Можно ли использовать лямбду , если вы также можете использовать простой объект для хранения тех же данных?

class Test:
    def __init__(self, some_data):
        self.some_data = some_data

    def f(self, x):
        print(x, self.some_data)

t = Test('123')
t.f('hello')

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

При захвате переменной в определении лямбды исходная переменная, похоже, сохраняется.

Поскольку вы сделали это значением по умолчанию для аргумента 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

0 голосов
/ 08 октября 2018

Значение аргумента по умолчанию для аргумента вычисляется один раз, когда определяется функция или лямбда.Это не оценивается на каждом сайте вызова.(Вот почему вы обычно не можете использовать [] в качестве аргумента по умолчанию и должны вместо этого указывать None и писать код для выделения нового списка при каждом вызове функции.)

Это действительно зависит отокружающий код, если подходит лямбда, функция или класс.Обычно, если есть только одна операция, и состояние не может быть изменено непосредственно извне (только в пределах операции), подходит лямбда или функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...