Higher Order Functions on Python - python

I am given a list of functions and asked to define plus(x,y) with add1 and repeated. plus is a function that takes in two numbers and returns the total. However, I cannot get any output with my definition. It just gives the name of the function. Any help is appreciated!
add1 = lambda x: x + 1
def compose(f, g):
return lambda x: f(g(x))
def repeated(f, n):
if n == 0:
return lambda x: x
else:
return compose(f, repeated(f, n - 1))
def plus(x, y):
return repeated(add1, y)

That is an interesting way to do addition. It works quite well, you just missed one thing. Repeated returns a function which will give the sum, not the sum itself. So you just have to call repeated(add1, y) on x like this
def plus(x, y):
return repeated(add1, y)(x)
The rest of the code works fine.

The detail is that plus returns a function and that's why you see the name of the function instead of a numeric value. I think that's why there is the x parameter in plus. Just change this line of code to
return repeated(add1, y)(x)
This will evaluate the return function of repeated with the value in x.
So using
plus(5, 1)
>> 6

Related

Is there a way to have a lambda reference inside a function always return the opposite bool value?

If I have a function that takes in a lambda reference as a parameter, and returns that reference so when it's called, it returns the value of that lambda function (boolean).
Is there a way to have it return the opposite boolean value?
def returns_diff(lambda_function):
return lambda_function
f = returns_diff(lambda x : x > 2)
f(0)
# I know I can do it this way but I want to do it inside the function.
# print(not(f(0)))
---> Should return True because it's supposed to return False since 0 is not bigger than two (return the opposite value of the lambda function)
I know I can just do: not(f(0)) when calling it, but I want to do it inside the function, not when I call it.
If you want to generate a function that returns the boolean opposite of a given function, you can do it like this:
def returns_diff(func):
return lambda x: not func(x)
f = returns_diff(lambda x: x>2)
f(0) # returns True
That's assuming the functions take one argument, as in your question. You can also make a version that works for functions with any number of positional or keyword arguments:
def returns_diff(func):
return lambda *args, **kwargs: not func(*args, **kwargs)
Can i use classes? Or it need to be just plain functions? With classes i would do
class diff:
def __init__(self,lambda_func):
self.lambda_func = lambda_func
def __call__(self,x):
return not(self.lambda_func(x))
f = diff(lambda x: x > 2)
f(0) #True

Using the lambda function for a function that depends on the input

As an input, I have a list of nonnegative whole numbers which are supposed to be the coefficients of a polynomial. But I also want to evaluate the polynomial for a certain number x.
For example:
If we have L=[2,3,1] as an input and x=42 we get 2x^2+3x+1=3655
What I want is for example:
>>>p=polynomial([2,3,1])
>>>p(O)
1
>>>p(42)
>>>3655
I guess I have to make use of the lambda function somehow, and I do know how it works for two variables on a given function, but in this case the function depends on my input.
def polynomial(coef):
coef=coef[::-1]
for i in range(len(coef)):
p=lambda x: coef[i]*x**i
p+=p
return lambda x: p
This is of course absolute nonsense, as I cannot add up one lambda function to another, but this is what my approaching "intuition" is.
Some hints are much appreciated.
The most obvious pythonic solution (using a closure - with a lambda or (preferably) a named inner function) has already been posted, but for the sake of completeness I'll add the other pythonic solution - the OO version using a custom callable class:
class Polynomial(object):
def __init__(self, coef):
self.coef = coef
def __call__(self, x):
n = len(self.coef) - 1
return sum(c * x ** (n - i) for (i, c) in enumerate(self.coef))
p = Polynomial([2,3,1])
print p(0)
print p(42)
Simple Python:
def make_poly(coefs):
def poly(x):
result = 0
for c in coefs:
result = result * x + c
return result
return poly
p = make_poly([2,3,1])
print(p(0))
print(p(42))
EDIT: code modified as suggested by Mark Dickinson in the comments
You can do it using lambda:
def polynomial(coef):
n = len(coef) - 1
return lambda x : sum([c * x ** (n - i) for (i, c) in enumerate(coef)])
Lambda isn't necessary however, you can define another function inside the polynomial function like so:
def polynomial(coef):
def f(x):
n = len(coef) - 1
return sum([c * x ** (n - i) for (i, c) in enumerate(coef)])
return f
Edit: Previously input was tied to 3 coefficients
The following lambda function evaluates a polynomial function, input as a coeff list of coefficients, in a given x:
from functools import reduce
lambda coeff, x: reduce(lambda a, b: a*x + b, coeff)
It seems that you want to generate these polynomial functions. You can still do it with this method:
def generate_polynomial(coeff):
return lambda x: (lambda y: reduce(lambda a, b: a*y + b, coeff))(x)
>>> p = generate_polynomial([20,0,17])
>>> p(10)
2017
This is merely based on Horner's algorithm.
Besides, if you want to use exclusively lambda and no built-in functions, you can also emulate reduce with lambda functions. You might want to give a look at Python - Removing duplicates in list only by using filter and lambda and Removing duplicates using only lambda functions, showing how to get rid of the filter function.

Calculate derivative for provided function, using finite difference, Python

I should probably start by saying that I am relatively new to python, but I have coded in java and Matlab before.
In python, the code
def func(f):
return f
g = func(cos)
print(g(0))
gives the result
>1.0
as g now is defined as the cosine function.
I want to write a function that calculates the derivative of any provided function using a finite difference approach. The function is defined as
def derivator(f, h = 1e-8):
and would like to achieve the follwing:
g = derivator(cos)
print(g(0)) # should be about 0
print(g(pi/2)) # should be about -1
At the moment my derivator function looks like this
def derivator(f, h = 1e-8):
return (f(x+h/2)-f(x-h/2))/h
which definitely is wrong, but I am not sure how I should fix it. Any thoughts?
Your current derivator() function (which should probably be called differentiator()) uses an undefined variable x and would return a single value, if x were defined--the value of f'(x). You want to return a function that takes an x value. You can define an inner function and return it:
def fprime(x):
return (f(x+h/2)-f(x-h/2))/h
return fprime
Because you don't use that function anywhere else, though, you can use lambda instead, which is also shorter:
return lambda x: (f(x+h/2)-f(x-h/2))/h
The only thing PEP 8 says about lambdas is that you should not assign the result of the lambda to a variable, then return it:
fprime = lambda x: (f(x+h/2)-f(x-h/2))/h # Don't do this!
return fprime
Make an inner function inside your derivator function and return it:
from math import cos, pi
def derivator(f, h = 1e-8):
def g(x):
return (f(x+h/2)-f(x-h/2))/h
return g
g = derivator(cos)
print(g(0)) # 0.0
print(g(pi/2)) # -0.999999993923
f and h will be part of the closure of the returned function.
You can also return a lambda expression to make it one line:
return lambda x: (f(x+h/2)-f(x-h/2))/h

lambda in python

I'm revisiting some scheme excercises in python (if that makes sense) to find out what python can do in terms of FP. My problem concerns lambda in python :
Can i define a general function in python with an operator as one of the arguments?
Think this :
def f (op,x,y):
#return some lambda function that combines x and y in the appropriate way
#i.e if op is +, then return x+y, if op is -, then return x-y etc
#Edit : added usage
#this should be called like this:
f(+, 1,2) #should return 3
I know this is possible in scheme, but is there something equivalent in python? I've gotten the impression that lambda in python is just a shorter way of defining a method, and I've not found any way to define a general combiner function in python.
I can see some points in your question, lets go through them in order:
1. Can I pass a function as a parameter to someone?
Yes:
def f(op, x, y):
return op(x, y)
def add(x, y):
return x + y
f(add, 10, 7) #gives 17
2. What about operators then?
Unlike scheme, Python operators are not functions so you can't pass them directly as parameters. You can either create the wrapper functions yourself or you can import the operator module from the standard library.
import operator
operator.add(1, 2)
(lambda x,y : x+y)(1, 2)
Operators not being real functions is a little sad in most cases but at least Python gives us chained comparisons like 10 <= x < 100 in exchange...
3. So what is the difference between Python and Scheme then?
In the general sense, functions in Python are as powerful as functions in Scheme, however there are some things to note:
The lambda keyword is limited
You can only have a single expression as the function body
f = lambda x, y: x + y
Since there are a bunch of things in Python that are statements and not expressions (assignments, the 2.x print, ...), you often need to fall back to named functions instead.
There are closures
def make_printer(msg):
def printer():
print msg
return printer
printer('a message')()
But mutating variables in them is a pain
This doesn't work. It tries to bind a new n for the inner function instead of using the outer one
def make_counter(n):
def inc():
n = n + 1
return n
return inc
new 3.x nonlocal keyword
def make_counter(n):
def inc():
nonlocal n
n = n + 1
return n
return inc
workaround w/ mutable objects
def make_counter(n):
nw = [n]
def inc():
nw[0] = nw[0] + 1
return nw[0]
return inc
Objects instead of closures. Uses the magic __call__ method to pretend its a function
class Counter:
def __init__(self, n):
self.n = n
def __call__(self):
self.n += 1
return self.n
Operators aren't really function in python, more like methods -- x + y is short for x.__add__(y), or y.__radd__(x). You can use the functions in the operator module to emulate the behavior you want.
I think your best bet is to make a function that does the operator, and pass that:
def f(op, x, y):
return op(x, y)
f(lambda x, y: x + y, 1, 2)
Looks a little redundant though when you can do:
f = lambda x, y: x + y
f(1, 2)
You cannot syntactically pass an operator in python. E.g. f(+) is a syntax error. However, if you consider op to be any function, you can use def or lambda:
def f(op, x, y):
def op_func():
return op(x, y)
return op_func
or
def f(op, x, y):
op_func = lambda: op(x, y)
return op_func
In your case, you wish to evaluate the function:
def f(op, x, y):
return op(x, y)
Remember that Python is interpreted, so even def statements are evaluated at runtime.
[ If for some reason you need to, you can access the built-in operators as functions using the operator module: http://docs.python.org/library/operator.html ]
Check operator module. All python operators are available there in the form of functions.
example:
import operator
operate = lambda op, x, y: op(x, y)
operate(operator.add, 1, 2)

Evaluating function objects from within a function in Python

Lets say we have two defined function objects
add1 = lambda x: x+1
and
square = lambda x: x*x
now I want to have a function that calls and adds the result of these two functions.
What I thought would work is:
def addFuncs(f,g):
f+g
addFuncs(add1,square)(10)
Which I thought would give me an answer of 111 (10*10 + 10+1)
But that just gave me an error TypeError: unsupported operand type(s) for +: 'function' and 'function'
So I tried:
def addFunctions(f, g):
def getf():
return f
def getg():
return g
return getf() + getg()
But still to no avail...
However, if I do
def addFunctions(f, g):
return f
it pops out with 100, so it seems to evaluate the function on return, But I can't figure out how to get it to evaluate the functions first and then operate on them.
Any help would be greatly appreciated!
EDIT
Got it!
def addFunctions(f, g):
return lambda x: f(x) + g(x)
def addFuncs(f,g):
return lambda x: f(x) + g(x)
addFuncs(add1,square)(10)
Python doesn't support adding functions together which both of your attempts tried to do. Instead, you need to create a new function, such as with lambda which calls the original functions.
Your original idea will work if you instead call these functions and then add their return values, rather than trying to add them themselves;
def addFuncs(f,g,x):
f(x) + g(x)
This is because f and g are actually LambdaTypes, and the () operator calls them, allowing the + operator to add their return values. When you use the + operator on them directly, the + operator doesn't know how to add two LambdaTypes.
EDIT
To add a little more; the reason
def addFunctions(f, g):
def getf():
return f
def getg():
return g
return getf() + getg()
doesn't work is because you are, again, trying to add together two function objects. However, your example of
def addFunctions(f, g):
return f
WILL work, because this will simply return another function object, which is then called with an argument of value 10 in your statement
addFuncs(add1,square)(10)
addFuncs takes arbitrarily many functions as input and returns a function:
def addFuncs(*funcs):
def _addFuncs(*args):
return sum(f(*args) for f in funcs)
return _addFuncs
add1 = lambda x: x+1
square = lambda x: x*x
print(addFuncs(add1,square)(10))
yields
111

Categories

Resources