3

I'm trying to define multiplication over functions in Python, in pseudocode this is:

This should return a function in x, given f(x), g(x)

multiply_two_functions((f(x), g(x)) = f(x) * g(x)

I can do this in Haskell like so:

mult :: (Num b) => (a -> b) -> (a -> b) -> (a -> b)  
mult f g = h
    where h x = (f x) * (g x)

You might ask why I'd want to do this - I have a list of functions [f], and I want to reduce these with multiplication. Again, in Haskell:

reduce_mult list = foldl mult 1 list

Edit: How I'm using it in python, for completeness:

def prod_reduce(f_list):
    def identity(x):
        return 1
    def f_mult(f, g):
        def multiplied(x):
            return f(x) * g(x)
        return multiplied
    prod = identity
    for f in f_list:
        prod = f_mult(prod, f)
    return prod

Does anyone have any tips for the Python implementation?

Leon
  • 68
  • 5
  • If you use callable classes (i.e. implement [`__call__`](https://docs.python.org/2/reference/datamodel.html#object.__call__)) instead of regular functions, you can define whatever multiplication behaviour you want ( see https://docs.python.org/2/reference/datamodel.html#emulating-numeric-types). Or are you asking how to write the `multiply_two_functions` function? Could you give an example of how you'd use it in Python, for those of us unfamiliar with [tag:haskell]? – jonrsharpe Apr 23 '15 at 07:20
  • @jonrsharpe I edited the OP with an example of how I used it. – Leon Apr 23 '15 at 08:10

3 Answers3

6

Just write a function that returns a new function that returns the product of the results of the other functions:

def multiply_funcs(f, g):
    def multiplied(x):
        return f(x) * g(x)
    return multiplied
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
6

If you are asking how to implement a function to create a new function that multiples the results from the target functions, it would look something like:

def multiply_two_functions(f, g):
    """Return a new function for e.g. h(x) == f(x) * g(x)."""
    def h(*args, **kwargs):
        return f(*args, **kwargs) * g(*args, **kwargs)
    return h

Note the use of *args, **kwargs to handle any positional and keyword arguments (see e.g. What does ** (double star) and * (star) do for parameters?); the only limitation is that any pair f and g must be able to handle the same arguments that will be passed to h. In use:

>>> def f(x):
    return x + 1

>>> def g(x):
    return 2 * x

>>> h = multiply_two_functions(f, g)
>>> h(5)
60

If you want to actually make h = f * g work, you would have to implement a class with __call__ and __mul__:

class Func(object):

    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        return self.func(*args, **kwargs)

    def __mul__(self, other):
        def new_func(*args, **kwargs):
            return self(*args, **kwargs) * other(*args, **kwargs)
        return Func(new_func)

This can be used as follows:

>>> f = Func(lambda x: x + 1)
>>> g = Func(lambda x: 2 * x)
>>> h = f * g
>>> h(5)
60
Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
5

You can do almost the same thing in Python: return a lambda that multiplies the two functions.

def multiply_two_functions(f, g):
    return lambda x: f(x) * g(x)

Test:

def a(x):
    return 2 * x

aa = multiply_two_functions(a, a)
print(aa(0), aa(1), aa(2))

Output:

(0, 4, 16)
Carsten
  • 17,991
  • 4
  • 48
  • 53
  • Thanks - clear response (I can't believe I didn't see that, but never really thought of returning an anonymous function in Python) – Leon Apr 23 '15 at 07:37