1

I am trying to add some customized logic outside of an existing function. Here are the example:

# existing function that I cannot change
def sum(a, b, c, d):
  return a+b+c+d

# the function I want to build
def sumMultiply(a, b, c, d, multiplier):
  return multiplier * sum(a, b, c, d)

This is a stupid example, but essentially I want to build a new function that takes all the parameter of the existing function and add a few new arguments.

The above solution is problematic when the existing function changes its definition. For example:

# in some updates the original function dropped one parameter
def sum(a, b, c):
  return a+b+c

# the new function will give an error since there is no parameter "d"
def sumMultiply(a, b, c, d, multiplier):
  return multiplier * sum(a, b, c, d) # error

How can I specify the new function so that I do not need to worry about changing the new function definition when the existing function definition changes?

1
  • Not convinced this is doable. You might handle 1 less argument, as per example. How about renamed arguments? Extra arguments? sumMultiply‘s signature or its call to existing would need to change, would they not? If sumMultiply’s sig changes then the client code will be affected. I’d write up a solid test suite exercising all bits of the existing API you care about. Commented Feb 16, 2022 at 0:31

3 Answers 3

2

One way would be to use arbitrary positional or keyword arguments:

def sumMultiply(multiplier, *numbers):
    return multiplier * sum(*numbers)

def sumMultiply(multiplier, *args, **kwargs):
    return multiplier * sum(*args, **kwargs)

However, if you see yourself passing around the same set of data around, consider making a parameter object. In your case, it can simply be a list:

def sum(numbers):
    ...

def sumMultiply(multiplier, numbers):
    return multiplier * sum(numbers)

There are some additional downsides to using arbitrary arguments:

  • the arguments are implicit: you might need to dig through several layers to see what you actually need to provide
  • they don't play well with type annotations and other static analysers (e.g. PyCharm's refactorings)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! Are there anyway we can know what the arguments are in sumMultiply? For example, we want to add 1 to argument a in sumMultiply instead of just passing them in to sum function.
1

I would create a decorator function

def create_fun_multiplier(fun, multiplier=1):
    def multiplier_fun(*args):
        return multiplier * fun(*args)
    return multiplier_fun

def my_sum(a, b, c):
    return a + b + c

sumMultiply = create_fun_multiplier(my_sum, multiplier=2)
print(sumMultiply(3, 4, 7))

Comments

0

I would look at using keyword args for this problem.

eg.

def sum(a, b, c):
    return a + b + c

def sumMultiply(*args, multiplier=1):
    return multiplier * sum(*args)

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.