Search code examples
pythonjupyter-notebook

Passing many functions as arguments in a big function


I am trying to run a convergence algorithm for a multivariable function. The group of functions are as such:

def f(x,r,d): 
if r**2 - x**2 < 1e-15:
    return w0 + 2*d
else: return w0 + 2*d - 2*sqrt(r**2 - x**2)

def g(x,r,d): return 1/f(x,r,d)

def simpsons(function,size,lower_bound,upper_bound, **vars):
delta_x = (upper_bound - lower_bound)/(size - 1)
x = np.linspace(lower_bound,upper_bound,size)
points = (function(x, **vars))

result = (delta_x/3)*(points[0] + points[-1] + 2*sum(points[2:size - 2:2]) + 4*sum(points[1:size - 1:2]))
return result

def H(function,size,lower_bound,upper_bound, **vars): return simpsons(function,size,lower_bound,upper_bound, **vars)/V(**vars) - K

Here is my convergence algorithm:

def find_zero(function,eps,alpha, **vars):
error = 1
k = 1
result = init_value

while abs(error) > eps:
    error = function(**vars)
    result -= alpha/k*error
    k += 1

return result

I will later on describe a list of r to pass through the functions and in the end, solve for d. I do it like so:

for i in range(len(R)):
    d[i] = find_zero(H, eps, alpha, function = g, size = size, lower_bound = x0, upper_bound = xf, r = R[i], d = init_value)

But I got this error: TypeError: find_zero() got multiple values for argument 'function'

How do I fix this?


Solution

  • When you call find_zero(H, eps, alpha, function = g, size = size, ...), you're passing H as the first positional value, which is named function in the definition of find_zero. You're also passing g as a keyword argument named function. Those aren't compatible!

    If you don't want a keyword argument to be mistakenly bound to a named argument that you intend to pass postionally, you can make that argument positional only in the declaration.

    def find_zero(function, eps, alpha, /, **vars):
       ...
    

    In this definition, the arguments function, eps and alpha are all positional only, as they're before the / in the function signature. You must pass three arguments positionally when you call this function, and keyword arguments that happen to match the positional argument names will still end up in vars.

    Positional-only arguments have been in Python since version 3.8 (see PEP 570). If you're using an earlier version, you're out of luck and you'll need to rename either the positional or the keyword argument.