I'm trying to understand a solution to a problem that involves lambda functions, but I can't get just one part through my head.
Problem Statement
seven(times(five())) # must return 35
four(plus(nine())) # must return 13
eight(minus(three())) # must return 5
six(divided_by(two())) # must return 3
Requirements:
There must be a function for each number from 0 ("zero") to 9 ("nine")
There must be a function for each of the following mathematical operations: plus, minus, times, dividedBy (divided_by in Ruby and Python)
Each calculation consist of exactly one operation and two numbers
The most outer function represents the left operand, the most inner function represents the right operand
Division should be integer division. For example, this should return 2, not 2.666666...:
Solution
def zero(f = None): return 0 if not f else f(0)
def one(f = None): return 1 if not f else f(1)
def two(f = None): return 2 if not f else f(2)
def three(f = None): return 3 if not f else f(3)
def four(f = None): return 4 if not f else f(4)
def five(f = None): return 5 if not f else f(5)
def six(f = None): return 6 if not f else f(6)
def seven(f = None): return 7 if not f else f(7)
def eight(f = None): return 8 if not f else f(8)
def nine(f = None): return 9 if not f else f(9)
def plus(y): return lambda x: x+y
def minus(y): return lambda x: x-y
def times(y): return lambda x: x*y
def divided_by(y): return lambda x: x/y
My Issue
In def plus(y): return lambda x: x+y, how are both arguments passed to this function? I understand that it has something to do with "closure", but I'm not able to find any documentation that helps me understand it in this context.
For example: three(plus(one())) expands to return 3 if not plus() else plus(3).
Then, plus(3) expands to return lambda x: x + 3. Where does that x get its value from?
In def plus(y): return lambda x: x+y, how are both arguments passed to this function?
It doesn't -- or at least, plus() doesn't pass both arguments into the lambda function. plus(3) returns lambda x: x + 3 -- a function that takes in one argument and increments its argument by 3. This process is known as currying.
To address your example, three(plus(one())):
one() returns 1.
plus(one()) becomes plus(1) and returns lambda x: x + 1.
three(plus(one()) becomes three(lambda x: x + 1). three() calls the lambda function passed in with an argument of 3 and returns the resulting value. This gives a final result of 4.
Related
This question already has an answer here:
Compute a chain of functions in python
(1 answer)
Closed 7 months ago.
I am reading Joseph Howse OpenCV book. In the appendix, he's discussing creation of composite function from 2 other functions, as follows:
def createCompositeFunction(func1, func2):
return lambda x : func2(func1(x))
How could I write this for an arbitrary number of functions, like so
def createCompositeFunction(*funcs):
pass
I assume this should be done using recursion, but I can not wrap my head around it.
Any suggestions?
You don't need recursion; this is a simple iterative problem:
def createCompositeFunction(*funcs):
def apply(x):
for func in funcs:
x = func(x)
return x
return apply
def f1(x):
return x + 2
def f2(x):
return x * 3
def f3(x):
return x / 2
comp = createCompositeFunction(f1, f2, f3)
print("comp(1) =", comp(1))
print("comp(2) =", comp(2))
Running the above code will output:
comp(1) = 4.5
comp(2) = 6.0
What you're asking for in functional programming terms is a reducer higher-order function. Python provides functools.reduce to this end:
def reduce(function, iterable, initializer=None):
Where function should be an applicator, iterable is the chain of funcs you want to apply, and initializer is your argument.
Here's a simple example on one argument:
from functools import reduce
def sub1(a):
return a - 1
def mul2(a):
return a * 2
def apply(x, f):
return f(x)
def compose(*fns):
return lambda x: reduce(apply, fns, x)
print(compose(sub1, mul2)(4)) # => 6
You can partial or lambda in extra args as needed:
from functools import partial, reduce
from operator import mul, sub
def compose(*fns):
return lambda x: reduce(lambda x, f: f(x), fns, x)
print(compose(lambda x: sub(x, 2), partial(mul, 3))(4)) # => 6
There are a lot of ways to go with this sort of thing, so I'll leave it at this absent further information about your use case.
As it turns out, this is pretty much a more fleshed-out version of Compute a chain of functions in python.
#ggorlen offers an efficient solution using reduce. Here's a recursive form -
# right-to-left composition
def compose(f = lambda x: x, *funcs):
if not funcs:
return f
else:
return lambda x: f(compose(*funcs)(x))
# left-to-right composition
def compose(f = lambda x: x, *funcs):
if not funcs:
return f
else:
return lambda x: compose(*funcs)(f(x))
Using separate definitions for identity and comp2 may make it easier to see how things are working -
def identity(x):
return x
def comp2(f, g):
return lambda x: f(g(x))
# right-to-left composition
def compose(f = identity, *funcs):
if not funcs:
return f
else:
return comp2(f, compose(*funcs))
# left-to-right composition
def compose(f = identity, *funcs):
if not funcs:
return f
else:
return comp2(compose(*funcs), f)
Here's a complete demo using left-to-right compose and a curry helper. Because curry accepts function as input, we can conveniently use it as a decorator too -
def curry(arity):
def loop(f, n, args):
return f(*args) if n == 0 else lambda x: loop(f, n - 1, (*args, x))
return lambda f: loop(f, arity, ())
#curry(2)
def add(x, y):
return x + y
#curry(2)
def mul(x, y):
return x * y;
myfunc = compose(add(1), mul(2), mul(2), mul(2))
print(myfunc(0))
# (((0 + 1) * 2) * 2) * 2
# 8
You can use accumulate from functools (and keep intermediate results):
from itertools import accumulate
def f1(x): return x + 2
def f2(x): return x * 3
def f3(x): return x / 4
def createCompositeFunction(func1, func2):
return lambda x: func2(func1(x))
# For x=3
l = [f(3) for f in accumulate([f1, f2, f3], createCompositeFunction)]
Output:
>>> l
[5, 15, 3.75] # <- the last item l[-1] is the final value
#larsks has a pretty nice answer. If you're interested in recursion specifically, here's an option:
def createCompositeFunction(*funcs):
func = funcs[0]
funcs = funcs[1:]
if len(funcs) == 0:
return func
return lambda x: func(createCompositeFunction(*funcs)(x))
def square(x):
return x ** 2
square_thrice = createCompositeFunction(square, square, square)
print(square_thrice(2))
Output:
>>> 256
Recursive approached: Assumed that the range of each function is the same of the domain of the next one.
The freedom in the initial value infers a condition on the outputs of the function, it cannot be None (filter as is not None to avoid automatic casting, i.e. 1<-->True, ''<-->False, ...).
def direct_composition(funcs, init_value=None):
if funcs:
if init_value is not None:
return direct_composition(funcs[1:], funcs[0](init_value))
return direct_composition(funcs[1:], funcs[0]())
return init_value
# sample functions
def a0(): return 'a' # initial function with no args
def a(x): return 'a'+x
def b(x): return 'b' + x
def c(x): return 'c' + x
# test with initial function taking parameters
funcs = a, b, c
direct_composition(funcs, '>')
#cba>
# test with initial function taking no parameters
funcs = a0, a, b, c
direct_composition(funcs)
#cba
Double layer approach with no side-effects, no restriction on the output of the functions. A pushward is when you fix a function that will be the most internal one and the other functions will be applied in increasing order to it.
def pushforward(f, initial_value=None):
def apply(value, funcs):
if funcs:
return apply(funcs[0](value), funcs[1:])
return value
return (lambda funcs: apply(f(initial_value), funcs)) if initial_value else (lambda funcs: apply(f(), funcs))
# with no initial value
f_init = a0
funcs = a, b, c
res = pushforward(f_init)(funcs)
print(res)
# with initial value
f_init = a
funcs = b, c
res = pushforward(f_init, '>')(funcs)
print(res)
I am trying to define a function f() that will use a function g() n times - f(g(x), n) - to modify a single input. The thing is, I want to make it so that f(g(x), n) will output another function k(), such that k(a) will give me the final result. For example:
square = lambda x : x*x
test = f(square, 2)
test(2) = (2^2)^2 = 16
I have had many attempts, but most of the time a TypeError would occur.
Here is one of my attempts:
def square(x):
return x*x
def mainfunc(function, no_of_times):
def func(x):
if no_of_times == 0:
return x
else:
return function(mainfunc(function, no_of_times - 1))
return func
test = mainfunc(square, 2)
print(test(2))
Can I have some advice on whether I have had the correct approach? If not, what should I do?
Let's assume function and no_of_times are just global names. A function that applies function no_of_times times to a given value is easy to implement:
def func(x):
for _ in range(no_of_times):
x = function(x)
return x
But you want a function f that returns such a function. And also, function and no_of_times shall be parameters of f, not global variables. So simply wrap the func definition in the function f with the wanted signature and return the resulting inner function:
def f(function, no_of_times):
def func(x):
for _ in range(no_of_times):
x = function(x)
return x
return func
This works as wanted:
>>> f(lambda x: x*x, 2)(2)
16
>>> g = lambda x: x*x
>>> k = f(g, 2)
>>> k(2)
16
>>> g = lambda x: f'g({x})'
>>> k = f(g, 5)
>>> k('spam')
'g(g(g(g(g(spam)))))'
Implementing the inner function func in a functional style is left as an exercise to the reader. (And also wasn't what the question asked for.)
A few issues with your code:
You need to return 1 when you want to run the function zero times.
In the recursive part of mainfunc you use function(mainfunc(function, no_of_times - 1)). The use of the outer function is incorrect as you are calling your square function with a function object as its argument when it expects an int.That is why you get a TypeError: unsupported operand type(s) for *: 'function' and 'function'.
In the recursive part of the function you need square(x) * mainfunc(function, no_of_times - 1)(x).
Two points to note regarding point 3:
Your mainfunc returns func which expects an int as its argument. Thus, when you recurse you need to call it as follows: mainfunc(function, no_of_times - 1)(x).
Since you are now recursing no_of_times -1 you need to multiply by function(x) to ensure that your recursive function works as intended.
def square(x):
return x * x
def mainfunc(function, no_of_times):
def func(x):
if no_of_times == 0:
return 1
else:
return function(x) * mainfunc(function, no_of_times - 1)(x)
return func
test = mainfunc(square, 3)
print(test(3))
Output: 64
I would like to build the sum of functions in python. However, I don't know upfront the length of the sum. All functions are of similar type, i.e. having one input and same output type. For two something like this would work
In [180]: def H(f, g):
...: def _h(x):
...: return f(x) + g(x)
...: return _h
However, I would like to have something which is generic in the sense that I could write H(*args) and it returns me the sum of all function in args (also working for just one).
Am I correct that this is the only way to build sum of functions? I can't write something like h = f+g for two function ?
It is probably easier to write something that is extendable. And you should use the built-in function sum to do the actual summing. This returns a generator that applies each function to the input x:
def map_funcs(x, *funcs):
return (f(x) for f in funcs)
funcs = lambda x: x + 1, lambda x: x**2
x = 10
print(sum(map_funcs(x, *funcs)))
If you want to you can also make it a wrapper which returns something callable, similar to what you've already got:
def map_funcs(*funcs):
def wrapper(x):
return (f(x) for f in funcs)
return wrapper
funcs = lambda x: x + 1, lambda x: x**2
x = 10
print(sum(map_funcs(*funcs)(x)))
# 111
Yes, it's possible. You have to use the sum() builtin function that return the sum of all values in the given list. Before that, you of course have to compute the list of all the functions givent to H() run with the correct parameter:
def power_two(x):
return x**2
def plus_20(x):
return x + 20
def H(*args):
def _h(x):
_results = [f(x) for f in args]
return sum(_results)
return _h
if __name__ == '__main__':
the_func = H(power_two, plus_20)
final_result = the_func(2)
print("(2^2) + (2+20) = %s" % the_func(2))
print("(3^2) + (3+20) = %s" % the_func(3))
Returns:
(2^2) + (2+20) = 26
(3^2) + (3+20) = 32
Try this:-
def H(*args):
def _h(x):
for func in args:
z += func(x)
return z
return _h
Just loop around the functional arguments and then sum it. I guess simple?
I hope it helps!
I'm writing a python script that should take a list of functions, written as lambda expressions, and return the compose of all the function, but, I have an arrow in the script, maybe because of the way I'm using lambda expression. It seems like even after I give the returned function a number value, I get back a function, and not a number. This is what I've wrote:
def compose1(lst):
if lst == []:
return lambda x: x
else:
temp = (lst[len(lst)-1])
for i in range(len(lst)-2,-1,-1):
temp = lambda x: lst[i](temp)
return lambda x: temp
this is a tast for the function I've wrote, which says I have a mistake.
f = compose1([lambda x: x+1, lambda x: x*2, lambda x: x-1])
for x in range(10):
assert (f(x) == 1 + (x - 1) * 2)
f = compose1([lambda x: x-1, lambda x: x*2, lambda x: x+1])
for x in range(10):
assert (f(x) == (x + 1) * 2) - 1
I would apreciate some halp on this problem..
thanks :)
def compose(*funcs):
"""
compose(func[,...[, func]]) -> function
Return the composition of functions.
For example, compose(foo, bar)(5) == foo(bar(5))
"""
if not all(callable(func) for func in funcs):
raise TypeError('argument must be callable')
funcs = funcs[::-1]
def composition(*args, **kwargs):
args = funcs[0](*args, **kwargs)
for func in funcs[1:]:
args = func(args)
return args
return composition
f = compose(*[lambda x: x+1, lambda x: x*2, lambda x: x-1])
for x in range(10):
assert f(x) == (1 + (x - 1) * 2)
f = compose(*[lambda x: x-1, lambda x: x*2, lambda x: x+1])
for x in range(10):
assert f(x) == ((x + 1) * 2) - 1
It looks like your loop is just reimplementing what reduce does. Here's a functional look at your function composition problem:
def compose1(fnlist):
if not fnlist:
return lambda x: x
# compose 1 function of x from two others
def compose2fns(fn1, fn2):
return lambda x : fn1(fn2(x))
# or if you really love lambdas
# compose2fns = lambda fn1,fn2: lambda x: fn1(fn2(x))
# use reduce to cumulatively apply compose2fns to the functions
# in the given list
return reduce(compose2fns, fnlist)
This passes your tests just fine.
CODE GOLF:
I couldn't resist, here is a one-liner, even including your check for an empty input list:
compose1 = lambda fnlist: reduce(lambda fn1,fn2: lambda x : fn1(fn2(x)),
fnlist or [lambda x:x])
Your issue here is your logic.
for i in range(len(lst)-2,-1,-1):
temp = lambda x: lst[i](temp)
return lambda x: temp
This will set temp to a function. lst is a list of functions, lst[i] is a function. You call that, to give a value, and then you make a new function with lambda. You then return a function that gives that function.
Your return value is a function, that gives a function, that gives a value, hence your issue.
As a note, this code has other problems. if lst == []: should be if not lst:, for example. You should also never iterate by index, and instead iterate by value, as Python is designed. I can't actually work out what you are trying to achieve with your code, which shows how hard to read iterating by index is.
Your code currently does this:
If there are no values, return a function that returns the first argument.
If there is one value, return the function in the list.
If there are many values, return a function that returns a function that returns the first value retrieved by running the first function from the list.
I'm not sure what you were trying to do, but I'm pretty sure that isn't it.
I like this syntax:
f = do (lambda x: x-1) (lambda x: x*2) (lambda x: x+1)
for x in range(10):
assert f(x) == 1 + (x - 1) * 2
The implementation is surprisingly trivial:
class do(object):
def __init__(self, x):
self.fns = [x]
def __call__(self, x):
if callable(x):
self.fns.append(x)
return self
for f in self.fns:
x = f(x)
return x
I am studying the properties of functions in Python and I came across an exercise that asks to:
Write a function which returns de power of a number. Conditions: The function may only take 1 argument and must use another function to return the value of the power of a given number.
The code that solves this exercise is:
def power(x):
return lambda y: y**x
For example, if we would like to know the value of the power: 2^3, we would call the function like this: power(3)(2)
Here is what I would like to know:
Is there any way to write a function that, when called, has a similar structure: function()()().
In other words, is it possible to write a function, that requires three or more parentheses ()()() when called?
If it is possible, could you please give me an example code of that function and briefly explain it?
Also:
def power(x):
def power_extra(y):
return y
def power_another(z):
return z
return power_extra and power_another
Possible?
Sure you can:
def power_times(k):
"""use as power_times(k)(x)(y) => k * y^x"""
return lambda x: lambda y: k * y**x
print power_times(2)(3)(4) # returns 2 * 4^3 = 128
When you call this function with argument 2 (power_times(2)), it returns a lambda function that works like lambda x: lambda y: 2 * y ** x (that is, like your original function, only with an extra "times 2").
You can stack as many lambdas on top of each other as you like:
def many_lambdas(x):
"""many_lambdas(x)(y)(z)(q) => x + y * z^q"""
return lambda y: lambda z: lambda q: x + y * z ** q
print many_lambdas(1)(2)(3)(4) # prints 163
Indeed, it might be even clearer if you skipped using def at all, and just wrote:
many_lambdas = lambda x: lambda y: lambda z: lambda q: x + y * z ** q
Or, alternatively, you could skip using lambda ever and just use them as nested functions:
def many_funcs(x):
def many_funcs_y(y):
def many_funcs_z(z):
def many_funcs_q(q):
return x + y * z ** q
return many_funcs_q
return many_funcs_z
return many_funcs_y
print many_funcs(1)(2)(3)(4) # prints 163
#David's answer would aptly answer you question for fixed nested function calls. For undefined nesting, you may want to define a class and overload the __call__ method along with __repr__ and __int__ to serve your Purpose.
>>> class Power(object):
def __init__(self, value):
self.value = value
def __call__(self, value):
self.value **= value
return self
def __int__(self):
return self.value
def __repr__(self):
return str(self.value)
>>> print Power(2)(2)(2)(2)(2)
65536
>>> int(Power(2)(2)(2)(2)(2)) / 2
32768