How to construct such a functional-programming tool in Python? - python

I want a function named times(), in order to make:
times(func,2) equivalent to lambda x:func(func(x))
and times(func,5) equivalent to lambda x:func(func(func(func(func(x)))))
Is there such a tool in Python? What would the code looks like if I want to write it by myself?
Thanks!

I'd suggest to call this power(), since this is actually the nth power of a function. There is no such thing in the standard library, but you can easily implement it yourself:
def power(f, n):
def wrapped(x):
for i in range(n):
x = f(x)
return x
return wrapped

Thanks, Sven
I found a recursive way to do that, but yours looks more pythonic:
def power(func, n):
def lazy(x, i=n):
return func(lazy(x, i-1)) if i > 0 else x
return lazy
>>> power(lambda x:x*2,3)(9)
72
>>> power(lambda x:x*2,2)(9)
36
>>> power(lambda x:x*2,1)(9)
18
>>> power(lambda x:x*2,0)(9)
9
And a way implemented with decorator:
def powerize(n):
def wrapped(func):
def newfunc(*args):
return power(func,n)(*args)
return newfunc
return wrapped
#powerize(3)
def double_3(x):
return x*2
>>> double_3(8)
64

Related

Python negate boolean function

A python boolean function can easily be negated with lambda functions, but it's a bit verbose and hard to read for something so basic, for example:
def is_even(n):
return n % 2 == 0
odds_under_50 = filter(lambda x: not is_even(x), range(50))
I'm wondering if there is a function to do this in the standard library, which might look like:
odds_under_50 = filter(negate(is_even), range(50))
As far as I know there is no builtin function for that, or a popular library that does that.
Nevertheless, you can easily write one yourself:
from functools import wraps
def negate(f):
#wraps(f)
def g(*args,**kwargs):
return not f(*args,**kwargs)
g.__name__ = f'negate({f.__name__})'
return g
You can then use:
odds_under_50 = filter(negate(is_even), range(50))
The negate function works for an arbitrary amount of parameters of the given function: if you would have defined is_dividable(x,n=2). Then negate(is_dividable) is a function with two arguments (one optional) that would also accept these parameters.
In case of filter you can use ifilterfalse (or filterfalse in Python 3.x) from itertools.
You can create a decorator:
def negate(function):
def new_function(*args, **kwargs):
return not function(*args, **kwargs)
return new_function
def is_even(x):
return x % 2 == 0
print is_even(1)
print is_even(2)
is_odd = negate(is_even)
print is_odd(1)
print is_odd(2)
This decorator can also be used with #negate.
#negate
def is_odd(x):
return x % 2 == 0
With funcy's or toolz's compose function you can negate the function like that:
import operator
import funcy
is_odd = funcy.compose(operator.not_, is_even)
If you want to make it more readable:
def negate(func):
return funcy.compose(operator.not_, func)
is_odd = negate(is_even)
# or without creating the function directly
print(negate(is_even)(5))
The funcy library has a lot of other useful functions for functional programming.

From Haskell to Python: how to do currying?

I recently started coding in Python and I was wondering if it's possible to return a function that specializes another function.
For example, in Haskell you can create a function that adds 5 to any given number like this:
sumFive = (+5)
Is it somehow possible in Python?
I think the other answers are misunderstanding the question. I believe the OP is asking about partial application of a function, in his example the function is (+).
If the goal isn't partial application, the solution is as simple as:
def sumFive(x): return x + 5
For partial application in Python, we can use this function: https://docs.python.org/2/library/functools.html#functools.partial
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
Then, we must turn the + operator into a function (I don't believe there's a lightweight syntax to do so like in Haskell):
def plus(x, y): return x + y
Finally:
sumFive = partial(plus, 5)
Not nearly as nice as in Haskell, but it works:
>>> sumFive(7)
12
Python's design does not naturally support the evaluation of a multi-variable function into a sequence of single-variable functions (currying). As other answers point out, the related (but distinct) concept of partial application is more straightforward to do using partial from the functools module.
However, the PyMonad library supplies you with the tools to make currying possible in Python, providing a "collection of classes for programming with functors, applicative functors and monads."
Use the curry decorator to decorate a function that accepts any number of arguments:
from pymonad import curry
#curry
def add(x, y):
return x + y
It is then very easy to curry add. The syntax is not too dissimilar to Haskell's:
>>> add5 = add(5)
>>> add5(12)
17
Note that here the add and add5 functions are instances of PyMonad's Reader monad class, not a normal Python function object:
>>> add
<pymonad.Reader.Reader at 0x7f7024ccf908>
This allows, for example, the possibility of using simpler syntax to compose functions (easy to do in Haskell, normally much less so in Python).
Finally, it's worth noting that the infix operator + is not a Python function: + calls into the left-hand operand's __add__ method, or the right-hand operand's __radd__ method and returns the result. You'll need to decorate these class methods for the objects you're working with if you want to curry using + (disclaimer: I've not tried to do this yet).
Yup. Python supports lambda expressions:
sumFive = lambda x: x + 5
for i in range(5):
print sumFive(i),
#OUTPUT 5,6,7,8,9
Python functions can return functions, allowing you to create higher-order functions. For example, here is a higher-order function which can specialize a function of two variables:
def specialize(f,a,i):
def g(x):
if i == 0:
return f(a,x)
else:
return f(x,a)
return g
Used like this:
>>> def subtract(x,y): return x - y
>>> f = specialize(subtract,5,0)
>>> g = specialize(subtract,5,1)
>>> f(7)
-2
>>> g(7)
2
But -- there is really no need to reinvent the wheel, the module functools has a number of useful higher-order functions that any Haskell programmer would find useful, including partial for partial function application, which is what you are asking about.
As it was pointed out, python does have lambda functions, so the following does solve the problem:
# Haskell: sumFive = (+5)
sumFive = lambda x : x + 5
I think this is more useful with the fact that python has first class functions (1,2)
def summation(n, term):
total, k = 0, 1
while k <= n:
total, k = total + term(k), k + 1
return total
def identity(x):
return x
def sum_naturals(n):
return summation(n, identity)
sum_naturals(10) # Returns 55
# Now for something a bit more complex
def pi_term(x):
return 8 / ((4*x-3) * (4*x-1))
def pi_sum(n):
return summation(n, pi_term)
pi_sum(1e6) # returns: 3.141592153589902
You can find more on functional programming and python here
For the most generic Haskell style currying, look at partial from the functools module.

How to compose to functions several times?

I'm supposed to write a code which gets a mathematical function and a number and gives me as an output a function that is composed n times.
For example if n=3 I would get f(f(f(x))).
When I run my code I get an error, what should I fix in it?
Running examples :
>>> repeated(lambda x:x*x, 2)(5)
624
>>> repeated(lambda x:x*x, 4)(3)
43046721
This is my code :
def repeated(f, n):
g=f
for i in range(n):
g=lambda x: (g(g(x)))
return (g)
Return a new function that does the repeated applying only when called:
def repeated(f, n):
def repeat(arg):
return reduce(lambda r, g: g(r), [f] * n, arg)
return repeat
The reduce() method uses the list of f function references to create the right number of nested calls, starting with arg as the first argument.
Demo:
>>> def repeated(f, n):
... def repeat(arg):
... return reduce(lambda r, g: g(r), [f] * n, arg)
... return repeat
...
>>> repeated(lambda x:x*x, 2)(5)
625
>>> repeated(lambda x:x*x, 4)(3)
43046721
A version that doesn't use reduce() would be:
def repeated(f, n):
def repeat(arg):
res = arg
for _ in range(n):
res = f(res)
return res
return repeat
Depending on the context of your task (e.g. programming class), you might be interested in following straightforward solution:
def repeated(f, n):
if n < 1:
raise ValueError()
elif n == 1:
return f
else:
return lambda x: repeated(f, n-1)(f(x))
This is a naive recursive solution, which maps more directly to the requirements. If you already know about higher functions, such as reduce I suggest to go with Martijn Pieters solutions. Nevertheless this does work:
>>> repeated(lambda x:x*x, 2)(5)
625
>>> repeated(lambda x:x*x, 4)(3)
43046721
I thought this was an interesting enough problem that I wanted to think about it for a couple days before answering. I've created a set of generalizable, pythonic (I think), ways for composing a function on itself in the way described in the question. The most generic solution is just nest, which returns a generator that yields successively nested values of the function on the initial argument. Everything else builds off that, but the decorators could be implemented using one of the above solutions, as well.
#!/usr/bin/env python
"""
Attempt to create a callable that can compose itself using operators
Also attempt to create a function-composition decorator.
f(x) composed once is f(x)
f(x) composed twice is f(f(x))
f(x) composed thrice is f(f(f(x)))
This only makes sense at all if the function takes at least one argument:
f() * 2 -> f(?)
But regardless of its arity, a function can only return exactly one value (even if that value is iterable). So I don't think it makes sense for the function to have >1 arity, either. I could unpack the result:
f(x, y) * 2 -> f(*f(x, y))
But that introduces ambiguity -- not every iterable value should be unpacked. Must I inspect the function to tell its arity and decide whether or not to unpack on the fly? Too much work!
So for now, I just ignore cases other than 1-arity.
"""
def nest(func, arg):
"""Generator that calls a function on the results of the previous call.
The initial call just returns the original argument."""
while True:
yield arg
arg = func(arg)
def compose(n):
"""Return a decorator that composes the given function on itself n times."""
if n < 1: raise ValueError
def decorator(func):
def nested(arg):
gen = nest(func, arg)
for i in range(n):
next(gen)
return next(gen)
return nested
return decorator
class composable(object):
"""A callable that can be added and multiplied."""
def __init__(self, func):
self.func = func
def __add__(self, func2):
"""self(func2(x))"""
def added(a):
return self(func2(a))
return composable(added)
def __mul__(self, n):
"""self * 3 => self(self(self(a)))"""
def nested(a):
gen = nest(self, a)
for i in range(n):
next(gen)
return next(gen)
return composable(nested)
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
#compose(2)
def sq(x):
return x*x
#compose(4)
def qu(x):
return x*x
#composable
def add1(x):
return x + 1
compset = composable(set)
assert (compset + str.split)('abc def') == set(['abc', 'def']), (compset + str.split)('abc def')
assert add1(1) == 2, add1(1)
assert (add1 + (lambda x: x * x))(4) == 17, (add1 + (lambda x: x * x))(4)
assert (add1 * 3)(5) == 8, (add1 * 3)(5)
assert 625 == sq(5), sq(5)
assert 43046721 == qu(3), qu(3)

product of two functions

I have two functions, f and g. Both have the same signature: (x). I want to create a new function, z, with the same signature:
def z(x):
return f(x) * g(x)
except that I'd like to be able to write
z = f * g instead of the above code. Is it possible?
Something close is possible:
z = lambda x: f(x) * g(x)
Personally, I find this way more intuitive than z = f * g, because mathematically, multiplying functions doesn't mean anything. Depending on the interpretation of the * operator, it may mean composition so z(x) = f(g(x)), but definitely not multiplication of the results of invocation. On the other hand, the lambda above is very explicit, and frankly requires just a bit more characters to write.
Update: Kudos to JBernardo for hacking it together. I was imagining it would be much more hacky than in turned out. Still, I would advise against using this in real code.
The funny thing is that it is quite possible. I made a project some days ago to do things like that.
Here it is: FuncBuilder
By now you can only define variables, but you can use my metaclass with the help of some other functions to build a class to what you want.
Problems:
It's slow
It's really slow
You think you want that but describing functions the way they meant to be described is the right way.
You should use your first code.
Just as a proof of concept:
from funcbuilder import OperatorMachinery
class FuncOperations(metaclass=OperatorMachinery):
def __init__(self, function):
self.func = function
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
def func(self, *n, oper=None):
if not n:
return type(self)(lambda x: oper(self.func(x)))
return type(self)(lambda x: oper(self.func(x), n[0](x)))
FuncOperations.apply_operators([func, func])
Now you can code like that:
#FuncOperations
def f(x):
return x + 1
#FuncOperations
def g(x):
return x + 2
And the desired behavior is:
>>> z = f * g
>>> z(3)
20
I added a better version of it on the FuncBuilder project. It works with any operation between a FuncOperation object and another callable. Also works on unary operations. :D
You can play with it to make functions like:
z = -f + g * h
I can be done with the exact syntax you intended (though using lambda might be better), by using a decorator. As stated, functions don't have operators defined for them, but objects can be made to be callable just like functions in Python --
So the decorator bellow just wraps the function in an object for which the multiplication for another function is defined:
class multipliable(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kw):
return self.func(*args, **kw)
def __mul__(self, other):
#multipliable
def new_func(*args, **kw):
return self.func(*args, **kw) * other(*args, **kw)
return new_func
#multipliable
def x():
return 2
(tested in Python 2 and Python 3)
def y():
return 3
z = x * y
z()

Import path for decorator-wrapped function?

Assuming I have a decorator and a wrapped function like this:
def squared(method):
def wrapper(x, y):
return method(x*x, y*y)
return wrapper
#squared
def sum(x, y):
return x+y
I have other code that would like to call the undecorated version of the sum function. Is there an import trick that can get me to this unwrapped method? If my code says from some.module.path import sum then, I get the wrapped version of the sum method, which is not what I want in this case. (Yes, I know I could break this out into a helper method, but that breaks some of the cleanliness of the pattern I'm going for here.)
I'm okay with adding extra "magic" to the decorator to provide some alternate symbol name (like orig_sum) that I could then import, I just don't know how to do that.
def unwrap(fn):
return fn.__wrapped__
def squared(method):
def wrapper(x, y):
return method(x*x, y*y)
wrapper.__wrapped__ = method
return wrapper
#squared
def sum(x, y):
return x+y
sum(2,3) -> 13
unwrap(sum)(2,3) -> 5
What about this?
def squared(method):
def wrapper(x, y):
return method(x*x, y*y)
return wrapper
def sum(x, y):
return x+y
squared_sum = squared(sum)
It's still a decorator, but you still can import squared and sum without any magic. Not sure if that's what you meant by 'helper method', but I find this much cleaner than a sum method, which actually sums the squares of its inputs.

Categories

Resources