Форум сайта python.su
0
Чувствую, что в голове есть некоторая неясность в принципах работы с лямбда функциями….Прошу помочь полностью разложить по полочкам проблему лямбда функции, так, чтобы я мог ответить на любой вопрос по этой теме ).
Предлагаю начать с разбора найденной на другом сайте строки с участием этих чертовок:
map(lambda n: (lambda f, *a: f(f, *a))(lambda rec, n: 1 if n == 0 else n*rec(rec, n-1), n), range(10))
Насколько я сейчас понимаю ситуацию, то лямбда функция имеет стандартную запись, например:
map(lambda x: x + 1, range(a))
По моим соображениям в этой записи все устоено так:
- объявляется функция lambda
- указывается условное название элемента итерируемого объекта в формулах функции, в данном случае “х”
- далее идет двоеточие “:” говорящее, что далее будет собственно описание действий функции
- далее идет само описание действия
- далее запятая, говорящая, что описание функции кончилось
- далее идет ссылка на итерируемый объект, элементы которого, под условным названием “х”, будут подвергаться экзекуции.
Обладая таким представлением я попытался разобраться, как работает строка, которая упоминалась выше….и понял, что я что то не понимаю в этой ситуации…
если с первым упоминанием lambda функции еще более-менее ясно, что есть аргумент n, есть некое описание фунции и после запятой есть итерируемый объект range(10)
map(
lambda n:
(lambda f, *a: f(f, *a))(lambda rec, n: 1 if n == 0 else n*rec(rec, n-1), n),
range(10)
)
то при детальном рассмотрении второго упоминания lambda функции я попал в ступор…совсем не понял запись:
lambda f, *a: f(f, *a)
Если не будет возражений, то именно с этого места и начнем…. Кто нибудь знает, как объяснить сию запись?
Отредактировано first-step (Апрель 4, 2019 21:33:48)
Офлайн
857
Для начала нужно разделить понятия лямбда-функции и лямбда-функции, реализованной в питоне. В питоне она однострочная, тогда как в общем определении (для всех языков программирования) такого ограничения нет.
Дальше в питоне у функций есть свои, питоновские синтаксические конструкции, которых нет в других языках. В частности здесь это видно по *a. Так что эти вещи к лямбда-функциям вообще не относятся.
В-третьих, передача функции в функцию - это вообще отдельный вопрос, который точно так же не имеет отношения к лямбда-функциям.
Также тут используется рекурсия, которая тоже к лямбда-функциям не относится.
Так что понять ты не можешь следующие понятия:
1) разница между лямбда-функцией, лямбда-функцией в питоне и лямбда-выражением в питоне;
2) распаковка аргументов функции в питоне;
3) функции как объекты первого класса;
4) рекурсивные вызовы функций.
Например, map() может принимать любую функцию, поэтому она может принимать и лямбда-функцию, так как лямбда-функция ничем не отличается от любой другой функции, у неё только имени нет. Лямбда-функцию можно создать отдельно и передать её в map() через ссылку, а можно создать динамически прямо на месте с помощью лямбда-выражения. Лямбда-выражение создаёт лямбда-функцию, поэтому результат лямбда-выражения можно сразу вызвать как функцию.
Вот пример
>>> res = (lambda x: x * 2)(5) >>> res 10 >>>
Отредактировано py.user.next (Апрель 5, 2019 02:11:59)
Офлайн
0
Спасибо за подробный ответ. Конечно я говорю про питон. Видимо его синтаксис я еще не выучил, поэтому меня заставила задуматься запись f(f, *a) … никогда с таким не сталкивался. Особенно в частности f(f Простите, а где почитать можно про это?
Или такая конструкция связана с записью lambda f…в частности f может быть именно эта?
Отредактировано first-step (Апрель 5, 2019 09:30:47)
Офлайн
857
first-stepЭто передача функции в функцию. Отношения к лямбда-функциям нет никакого.
Особенно в частности f(f Простите, а где почитать можно про это?
>>> def f(func1, func2): ... print('function1 is', func1) ... print('function2 is', func2, 'call result is', func2()) ... >>> def g(): ... return 2 * 2 ... >>> f(f, g) function1 is <function f at 0x7f73dc83fea0> function2 is <function g at 0x7f73d4672620> call result is 4 >>> >>> f(print, lambda: 1) function1 is <built-in function print> function2 is <function <lambda> at 0x7f73d4672620> call result is 1 >>> >>> f(print, list) function1 is <built-in function print> function2 is <class 'list'> call result is [] >>>
Отредактировано py.user.next (Апрель 5, 2019 10:06:35)
Офлайн
0
py.user.nextСпасибо, передачу функции в функцию слышал, но не внимательно, сейчас плотнее изучу.
Это передача функции в функцию
Отредактировано first-step (Апрель 5, 2019 13:10:34)
Офлайн
857
first-stepf - это просто имя аргумента. Это так же, как и в примере выше, имя func1 или func2 - это имена аргументов функции.
Откуда взялась функция с названием f?
lambda arg1, *arg2: arg1(arg1, *arg2)
>>> (lambda arg1, *arg2: arg1(arg1, *arg2))(print, 1, 2, 3) <built-in function print> 1 2 3 >>>
Отредактировано py.user.next (Апрель 5, 2019 14:46:12)
Офлайн
0
Вот в предыдущем примере мне как раз все понятно. Все по-людски. Есть объявление def и т.д
А вот в записи
lambda arg1, *arg2: arg1(arg1, *arg2)
Офлайн
857
first-stepДа, это перечисление аргументов функции.
До двоеточия - идет перечисление аргументов?
first-stepПосле двоеточия идёт однострочное тело функции. Тело функции срабатывает, когда функцию вызываешь.
а после двоеточия что?
first-stepВ эту функцию подали функцию. Поданная функция прикрепилась к аргументу и аргумент стал функцией. Дальше аргумент вызывается, потому что это функция. А в вызов этой функции подаётся этот же аргумент. Это как в функцию print() подать функцию print().
arg1 - каким то образом в функцию превратился?
>>> print(print, print, print) <built-in function print> <built-in function print> <built-in function print> >>>
Офлайн
0
Подождите, подождите… Уже близко решение)
py.user.next
В эту функцию подали функцию. Поданная функция прикрепилась к аргументу и аргумент стал функцией. Дальше аргумент вызывается, потому что это функция. А в вызов этой функции подаётся этот же аргумент. Это как в функцию print() подать функцию print().
Офлайн
857
first-stepКогда функцию вызвали и передали в вызов на место аргумента функцию. Вот я думаю, что ты просто не понимаешь разницы между определением функции и вызовом функции. Поэтому ты не можешь понять, где определение лямбда-функции, а где вызов лямбда-функции.
А вот arg1 в какую секунду превратился в функцию?
first-stepКруглые скобки вызывают тот объект, к которому привязано имя a, как функцию.
или любая запись типа a(b) - превращает a в функцию?
>>> a = 1 >>> >>> a('x') Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not callable >>> >>> a = print >>> >>> a('x') x >>>
Отредактировано py.user.next (Апрель 5, 2019 16:07:29)
Офлайн