Let's say I have this function in a python module:
def functionmaker(a,b):
return lambda x: (a*x) + b
Now let's say I am given a list of this format:
ablist = [[a1, b1], [a2, b2]...[an, bn]] of arbitrary length.
My goal is to add up all the resulting functions you get from these a's and b's.
Of course, with the simple example I gave of ax+b, you could algebraically work it out to being (a1 + a2 + ... an)x + (b1 + b2 + ... bn). But let's ignore that for a moment. The function I am actually working with is a contracted gaussian molecular orbital function, and it's not as easy to trick your way out of the problem with algebra.
What I wanted to do was something like this:
function = lambda x: (a1*x) + b1
q = 2
while q < n:
function = lambda x: function(x) + (ablist[q][0]*x) + ablist[q][1])
q += 1
But it seems you can't call a function inside itself like that. I was hoping it would just over-write the old version of "function" with the new one, but I guess not. I guess I probably need to do some kind of recursive way, but maybe there is a nicer way?
By the way I am using python 2.7.
You can do something like this:
>>> def functionmaker(a, b):
... return lambda x: a*x + b
...
>>> def summer_funcs(args):
... return lambda x: sum(functionmaker(*a)(x) for a in args)
...
>>> arguments = [(1,2), (3,4), (5,6)]
>>> summer_funcs(arguments)(1)
21
Or if you prefer:
>>> f = summer_funcs(arguments)
>>> f(1)
21
>>> f(2)
30
If I've correctly understood your question, you could use the built-in sum() function and pass it a generator expression argument to accomplish the goal:
def functionmaker(a, b):
return lambda x: (a*x) + b
ablist = [(1,2), (3,4), (5,6)]
x = 1
total = sum(functionmaker(a, b)(x) for a, b in ablist)
print(total) # -> 21
If you need to compute this quantity for many different values of x, then it might be worthwhile to optimize things for doing that:
functions = [functionmaker(a, b) for a, b in ablist]
sum_of_functions = lambda x: sum(function(x) for function in functions)
for x in (1, 1.5, 2):
print('sum_of_functions(x={:.1f}) -> {:.1f}'.format(x, sum_of_functions(x)))
Output:
sum_of_functions(x=1.0) -> 21.0
sum_of_functions(x=1.5) -> 25.5
sum_of_functions(x=2.0) -> 30.0
Related
I got stuck on that:
a list y = (1,2,3...)
a function func(A,B)
a constant C
How can I express this situation with loops?
B1 = func(C , y[0])
B2 = func(B1 , y[1])
B3 = func(B2 , y[2]) #.... and so on.
The first argument is just the return value of the previous call, starting with C:
result = C
for yval in y:
result = func(result, yval)
As pointed out in the comments, this pattern is captured by the often overlooked reduce function. (Overlooked, in part, because it was demoted from the built-in namespace to the functools module in Python 3.)
from functools import reduce
result = reduce(func, y, C)
There are a few ways to do this:
First of all, regular loop:
C = ... # the constant
b = C
for i in y:
b = func(b, i)
But using a reduce like this, is my preferred way of doing this:
from functools import reduce
b = reduce(func, y, C) # the last arg being the initial item used
You could also use the walrus notation, which is only useful (IMO) when saving the intermediate states.
bs = [(b := func(b, yi)) for yi in y)]
b # b being the end result
I'm curious if it is possible to avoid lambda expressions in the following case.
For example using lambda expression I can simple define a function that returns a lambda exp.
def square_fun(a,b,c):
return lambda x: a*x**2 + b*x + c
After we can call it using:
f = square_fun(1,2,3)
f(1) # here x = 1
How can I get the same behaviour avoiding lambda expression?
for example, square_fun must return another function
def square_fun(a,b,c):
return f...
In python you can define a function inside another function, so the following snippet should give you the same behavior:
def square_fun(a, b, c):
def result(x):
return a*x**2 + b*x + c
return result
f = square_fun(1, 2, 3)
print(f(1))
# Should print 6
So, I'll try to explain what's going on here:
In the line f = square_fun(1, 2, 3), f will actually be mapped to the internal function (aka. result)
Please note that return result does not have the () at the end, hence the function is not called yet
The function gets called in print(f(1)) and the variable x takes 1 as its value
Finally the result function returns the computed value using x, and a, b and c (from square_fun(1, 2, 3))
You can find additional info here => https://www.learnpython.org/en/Closures
You can also use functools.partial:
from functools import partial
def square_fun(x, a, b, c):
return a * x ** 2 + b * x + c
f = partial(square_fun, a=1, b=2, c=3)
print(f(1))
# should print 6
I am busy just doing some code on the bisection method. It is easy of course to just write the script and run it. However, the trick comes in when I want to define a function that will take an expression such as x**2 as an input. I've scrapped something together though. It sort of gets the job done but then at my first if statement it complains about not being able to multiply a function by a function. How would I solve this problem as well?
I really tried doing my homework on this problem before asking and unfortunately cannot find the solution. I would just love to know how to do this though.
from sympy.abc import x
def bisect(f, a, b):
f = lambda x: f
f_a, f_b = f(a), f(b)
tol = 1e-4
count = 0
print '\t'.join( ['Step' , 'a', 'b', 'c', 'f(c) ' , '(b-a)/2)'])
while (b-a)/float(2) > tol:
c = (a+b)/2
f_c = f(c)
print '\t'.join( [str(count) , str(a) , str(b) , str(c), str((b-a)/float(2) )])
if f_a*f_c < 0:
b = c
f_b = f_c
else:
a = c
f_a = f_c
count = count + 1
Is this what you need to know?
>>> def demo(func):
... for i in range(5):
... print func( float(i))
...
>>> demo( lambda x: x**2 + 2*x - 5 )
-5.0
-2.0
3.0
10.0
19.0
You can also pass in a function created with def as well as a one-liner defined with lambda. the above is the same as
def foo(x):
return x**2 + 2*x - 5
demo( foo)
The other thing you might want to know is that
definition = "x**2 + 2*x - 5" # or read it from the user as text input
demo( eval( "lambda x: " + definition))
works ...
obligatory warning, "eval is evil", accepting Python code from a user and executing it is generally regarded as a security no-no-NO! However, if this code is run by the same user who is experimenting with plotting mathematical forms, no great harm can come of it. He can't do anything worse than what he could do with python at the command line. If you were to do anything like this in a web-server or suchlike, I would fear for your employment and future prospects thereof!
Let's assume you have created an expression for function f using sympy:
f = x**2-0.1
Your bisect function will work if you change the lambda definition:
def bisect(fexpr, a, b):
f = lambda xval: fexpr.subs(x,xval)
f_a, f_b = f(a), f(b)
...
Hi I am new to functional programming. What i did is
>>> g=lambda x:x*2
>>> f=g
>>> g=lambda x:f(f(x))
>>> g(9)
36
Now, it is not creating g as a nonterminating recursive function - g(x) is transformed to a new function which gives the result g(g(x)).
>>> f=g
>>> g=lambda x:f(f(x))
>>> f(8)
RuntimeError: maximum recursion depth exceeded
I expected g to be transformed into a function which gives the result g(g(g(x))), according to the first definition of g(x). Why does it not? Is it possible to make a new function which results in g(g(g(...(g(x))....))) for a certain number of iterations in this way?
When you do f = g for the second time, f becomes lambda x: f(x). Closures are created by name, not by value.
This becomes easy with a helper function:
def compose(f, g):
return lambda x: f(g(x))
square = lambda x:x*2
g = square
for i in xrange(4):
g = compose(g, square)
In python, variables are names mapped to values, not values themselves (everything is a reference). Also, you can think of lambda as storing text that can be evaluated. The following will illustrate
a = 2
f = lambda x: a*x
f(2) # This gives 4
a = 3
f(2) # This gives 6
This should clear up why you are getting infinite recursion.
In answer to your question about recursing, here is a little hack that might do
g = lambda x, n: n > 0 and g(x, n-1)**2 or x
Then g(2,3) would be (((2)^2)^2)^2 = 256.
This
g=lambda x:x*2
f=g
g=lambda x:f(x)
is equivalent to:
f=lambda x:x*2
g=lambda x:f(x)
When you call g, you get whatever f happens to be defined in the global (or enclosing) scope.
what you're expecting is something like:
f=lambda x:x*2
g=lambda x, f=f:f(x)
That captures the value of f in the outer scope at the time the lambda expression is evaluated.
I'm having trouble with a question which follows: Write a recursive function repeatedlyApply that takes as arguments a function
f of one argument and a positive integer n. The result of repeatedlyApply is a function of one argument that applies f to that argument n times.
So, for example, we would have
repeatedlyApply(lambda x: x+1,10)(100) ==> 110
You may assume that the following function has been defined. You don't have to use it, but it can contribute to a pretty solution.
def compose(f,g):
return lambda x: f(g(x))
So far i've written this
def compose(f,g):
return lambda x: f(g(x))
def recApply(f,n):
for i in range(n):
return recApply(compose(f,f), n-1)
return f
I'm going wrong somewhere because using the above example recApply(lambda x: x+1,10)(100) i get 1124.
Help much appreciated
Correct answer is:
def recApply(func, n):
if n > 1:
rec_func = recApply(func, n - 1)
return lambda x: func(rec_func(x))
return func
And the output:
>>>> print recApply(lambda x: x+1,10)(100)
110
Your function needs some work:
You have a return inside your for loop, so you return immediately instead of running the loop.
You have a recursive call inside your for loop, so you are doing a bit too much iteration. Choose one or the other.
Be careful when you stack function compositions on top of each other, you are doing power composition rather than linear composition.
Can you tell us what precisely you are trying to do?
EDIT: Since everybody else is posting an answer:
recApply = lambda f, n: lambda x: x if n == 0 else recApply(f, n-1)(f(x))
I have a solution based on lambdas:
>>> f = lambda x: x + 10
>>> iterate = lambda f, n, x : reduce(lambda x, y: f(x), range(n), x)
>>> iterate(f, 10, 3)
103
>>> iterate(f, 4, 4)
44
>>> f10 = lambda x: iterate(f, 10, x)
>>> f10(5)
105
I assume this is an exercise of some sort. There are a few ways you could do it, here's a short one:
>>> repeatedlyApply = lambda f, n: reduce(lambda f1, f2: compose(f1, f2), [f]*n)
>>> repeatedlyApply(lambda x: x+1,10)(100)
110