Рассмотрим следующий фрагмент кода Python относительно функций состава:Какова логика этой конкретной композиции функций Python?
from functools import reduce
def compose(*funcs):
# compose a group of functions into a single composite (f(g(h(..(x)..)))
return reduce(lambda f, g: lambda *args, **kwargs: f(g(*args, **kwargs)), funcs)
### --- usage example:
from math import sin, cos, sqrt
mycompositefunc = compose(sin,cos,sqrt)
mycompositefunc(2)
У меня есть два вопроса:
- Может кто-то пожалуйста, объясните мне "логику работы"
compose
? (Как это работает?) - Было бы возможно (и как?) Получить то же самое without using reduce для этого?
Я уже смотрел here, here и here too, моя проблема НЕ понимание того, что lambda
средства или reduce
делает (я думаю, что я, например, что 2
в примере использования будет несколько первый элемент funcs
). Что я нахожу трудно понять, а сложность, как два lambda
s получил комбинированный/вложенная и смешивают с *args, **kwargs
здесь в качестве первого аргумента reduce
...
EDIT:
Прежде все, @Martijn и @Borealid, спасибо за ваши усилия и ответы и за то, что вы посвящаете мне. (Извините за задержку, я делаю это в свое свободное время и не всегда имеют аа много ...)
Хорошо, подходя к фактам сейчас ...
О 1-й точке на мой вопрос:
Прежде всего я понял, что я действительно не получил (а я надеюсь, что я сделал сейчас) об этих *args, **kwargs
переменного числа аргументов до того, что по крайней мере **kwargs
не является обязательным (я говорю хорошо, верно?) Это заставил меня понять, например, почему mycompositefunc(2)
работает с этим только одним (не ключевым) переданным аргументом.
Я понял, что пример будет работать даже при замене этих *args, **args
во внутренней лямбда простым x
. Я полагаю, это связано с тем, что в этом примере все три составные функции (sin, cos, sqrt
) ожидают один (и только один) параметр ... и, конечно же, возвращают один результат ... так, более конкретно, он работает, потому что составная функция ожидает только один параметр (следующие остальные будут естественно получить только один аргумент здесь, это результат предыдущих скомпонованных функций, поэтому вы НЕ МОЖЕТЕ составить функции, которые ожидают более одного аргумента после первого ... Я знаю, что это немного искажать, но я думаю, что вы получили то, что я пытаюсь объяснить ...)
Сейчас подходит к тому, что остается неясным, реальный вопрос для меня здесь:
lambda f, g: lambda *args, **kwargs: f(g(*args, **kwargs))
Как работает эта лямбда «магия»?
Со всем уважением вы заслуживаете, и я приношу вам, мне кажется, как вы оба неправы приходят к выводу, окончательный результат должен быть: sqrt(sin(cos(*args, **kw)))
. На самом деле этого не может быть, порядок работы функции sqrt явно отменяется: он не последний, а первый.
Я говорю это потому, что:
>>> mycompositefunc(2)
0.15531241172
его результат равен
>>> sin(cos(sqrt(2)))
0.15531241172
тогда вы получите ошибку с
>>> sqrt(sin(cos(2)))
[...]
ValueError: math domain error
(это связано с попытками SquareRoot отрицательным поплавок)
#P.S. for completeness:
>>> sqrt(cos(sin(2)))
0.7837731062727799
>>> cos(sin(sqrt(2)))
0.5505562169613818
Итак, я понимаю, что состав функций будет сделан от последнего к первому (т. Е. Составить (sin, cos, sqrt) => sin (cos (sqrt (x)))), но «Зачем? "и , как это делает лямбда вложенности„магия“работает? до сих пор остается неясным, немного для меня ... Помощь/Предложения очень оценили!
На 2-й точке (о перезаписи сочинить без уменьшения)
@Martijn Питерс: ваш первый Compose (далее "завернуты" один) работает и возвращает точно такой же результат
>>> mp_compfunc = mp_compose(sin,cos,sqrt)
>>> mp_compfunc(2)
0.15531241172
развернутая версия, instea d, к сожалению, петли до RuntimeError: maximum recursion depth exceeded
...
@Borealid: ваш пример foo/bar не получит больше двух функций для композиции, но я думаю, что это было просто для объяснений, не предназначенных для ответа на вторую точку, не так ли?
Лучше использовать 'lambda x: x' в качестве начального значения для' reduce' или цикл в вашем ответе: таким образом 'compose()' является правильным составом нулевых функций - функция это ничего не делает. – Lynn
@Mauris: но это не отразило бы результат функции 'reduce()', опубликованной в вопросе. –
@Mauris: Martijn прямо на том, что он не будет отражать оригинальную функцию, опубликованную в вопросе, приятное предложение в любом случае +1! – danicotra