1

I have:

def f(x, y): return x**2 + y**2
def g(x, y): return x**3 + y**3
def h(x, y): return x**4 + y**4

And I'd like to make a new function:

def J(x, y):
    return f(x,y)*g(x,y)*h(x,y)

However, I am unable to find a way to do this programmatically. That is, take something like:

myFunctions = [f,g,h]

and return a new function J which returns the product of f, g and h.

Another wrinkle is that while f, g and h will always have an identical number of arguments, that number could change. That is, they could all have could have five arguments instead of two.

Desired behaviour:

print(J(2, 2)) # 4096

EDIT

The number of functions in myFunctions is also arbitrary. I thought this was implied in my question, but upon rereading it I see that I did not make that at all clear. My apologies.

4
  • Any reason you don't define J as def J(*args, **kwargs) instead? Do you need the parameters for any other reason? Commented Aug 5, 2016 at 12:46
  • Do you create the list of functions? if it's so you can use *args to pass an optional number of positional arguments to your function. Commented Aug 5, 2016 at 12:46
  • You could use functools.reduce, operator.mul, functools.partial and other functional tooling in Python to do this. As other comments note, you can define arbitrary positional and keyword arguments easily. Commented Aug 5, 2016 at 12:48
  • @VincentSavard Not the names themselves, no. Commented Aug 5, 2016 at 12:52

4 Answers 4

3

A function can accept arbitrarily many arguments using * like this:

def J(*args):

This will store all of J's arguments in the list args. That list can then be converted back into multiple arguments to call other functions like this:

def J(*args):
  return f(*args) * g(*args)

This solves the problem of the number of arguments changing. So now let's handle the fact that there can be arbitrarily many functions. First we need to call the function in your list. We can just do that by iterating over them and using ():

def J(*args):
  return [func(*args) for func in myFunctions]

This will return a list of the functions' return values. So all we need now is to get the product of a collection:

from functools import reduce
from operator import mul

def product(numbers):
  return reduce(mul, list, 1)

def J(*args):
  return product(func(*args) for func in myFunctions)
Sign up to request clarification or add additional context in comments.

Comments

3

You could allow J to take as many arguments as necessary, then multiply the final list that f, g, and h give:

def f(x, y): return x**2 + y**2

def g(x, y): return x**3 + y**3

def h(x, y): return x**4 + y**4

def multiply(mylist):
    return reduce(lambda a, b: a*b, mylist)

myfuncs = [f,g,h]
def J(*args):
    return multiply([myfunc(*args) for myfunc in myfuncs])

Since f, g, and h will have the same amount of arguments, this should work for all cases.

1 Comment

Question is tagged Python 3, so you'll have to import reduce from itertools. Might as well also import operator.mul instead of building your own multiply function.
1

Another option:

from functools import reduce, partial
from operator import mul

def f(x, y): return x**2 + y**2
def g(x, y): return x**3 + y**3
def h(x, y): return x**4 + y**4

myFunctions = [f,g,h]

J = partial(lambda funcs, *args: reduce(mul, (func(*args) for func in funcs), 1), myFunctions)
print J(2, 2)

Has the nice property that J takes the same number of arguments as functions f, g & h rather than *args.

2 Comments

This doesn't use myFunctions though - it just hardcodes f, g and h.
Agreed, I've improved the answer (inspired by yours), thanks
0

The variable number of arguments problem can be resolved by this:

def f(*args): return sum(map(lambda x: x**2, args))

def g(*args): return sum(map(lambda x: x**3, args))

def h(*args): return sum(map(lambda x: x**4, args))

And then you could simply define the J function

def J(*args):
    return f(*args)*g(*args)*h(*args)

If you want to support variable number of functions, then you could define J as the following and pass in the list of functions as the first item of the list and the arguments as the following items.

def J(*args):
    funcs = args[0]            
    args = args[1:]           
    temp = map(lambda x: x(*args), funcs)
    return reduce(lambda x,y: x*y, temp, 1)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.