function that is sum of arbitrary many other functions

Hej! I'm trying to write a function in Python for a polynomial p that is a linear combination of n basis functions phi_i. How can I define a function that is itself a sum of n other functions?

I know that this works:

phi1 = lambda x: x**2
phi2 = lambda x: x
p = lambda x: phi1(x) + phi2(x)

But if I try a loop like this:

p = lambda x: 0
for i in range(0,n):
    p = lambda x: p(x)+phi[i](x)

where phi is a list of my basis functions, I create an infinite loop.


I checked Writing a function that is sum of functions, but unfortunately that's not in Python.


You can do this by passing a simple generator expression to sum :

def sigma(funcs, x):
    return sum(f(x) for f in funcs)

phi = [lambda x: x**2, lambda x: x]
y = sigma(phi, x)

BTW, it's considered bad style to use lambda for named functions, it's supposed to be for anonymous functions.


If you want a function that doesn't need phi to be passed in each time you call it, there are a couple of ways to do that. The easiest way is to simply use phi in the function. Eg,

def sigma(x):
    return sum(f(x) for f in phi)

However, that has a couple of downsides. It won't work if phi isn't in the scope where you call sigma ; you can get around that by making phi global, but that may not be convenient, and it's best to avoid globals when they aren't necessary. The other downside is that it uses the current contents of phi , not the contents it had when sigma was defined, so if you modify the contents of phi those changes will be reflected in sigma , which may or may not be desirable.

Another option is to use a closure to create the function. Then we won't be affected by the scope issue: you can call the resulting summing function inside a scope where the original function list isn't visible. We can also create a copy of the function list, so it won't be affected by changes to the passed-in function list.

def make_adder(funcs):
    # Copy the function list 
    funcs = funcs[:]
    def sigma(x):
        return sum(f(x) for f in funcs)
    return sigma

phi = [lambda x: x**2, lambda x: x]
sigma = make_adder(phi)
y = sigma(x)

Yet another option is to use my original sigma and pass it and the phi functions to functools.partial , eg

from functools import partial
sig = partial(sigma, phi)
y = sig(x)

Straight answer to OP

Store your phis in a list :

phis = [
    lambda x: x**2,
    lambda x: x,
]
p = lambda x: sum(phi(x) for phi in phis)

Further considerations

If you want to achieve a polynomial, I would suggest something similar to this:

def poly(c):
    return lambda x: sum(f(x) for f in [lambda x, i=i: c[i]*x**i for i in range(len(c))])

poly function accepts a sequence as the only argument, where its elements need to be int or float . The first element is assigned as the coeficient of x^0, the second to x^1 and so on. So your example (p(x) = x + x^2) would end up being constructed like this: p = poly([0, 1, 1])

Another option is to accept any number of arguments where each of them needs to be a int or float instead of the first being a sequence. This would only require to add one * to the function declaration.

def poly(*c):
    return lambda x: sum(f(x) for f in [lambda x, i=i: c[i]*x**i for i in range(len(c))])

To construct your example with this function you would not require the list: p = poly(0, 1, 1) .

Any of those methods would create a polynomic function that can be called as you would expect: p(1) would return 2 , p(2) would return 6 and so on.

Function explained

def poly(c):
    # Create a list where we are gonna store the functions for every term in the polynomial
    terms = []
    # Create as many terms as the arguments length
    for i in range(len(c)):
        # Each term is the product of the nth coefficient from c and x to the power of n
        terms.append(lambda x, n=i: c[n]*x**n)
        # The second parameter n is needed because if we pass i directly
        # inside the function algorithm, Python wouldn't check its value
        # inmediately, but when it gets executed, and by then the loop will
        # be finished and i would be constant for every term. This argument
        # is not exposed to the polynomial function as the next lambda only
        # has one argument, so there is no way to wrongly call this function
    # We return a function that adds the result of every term
    return lambda x: sum(f(x) for f in terms)
链接地址: http://www.djcxy.com/p/51120.html

上一篇: 创建一个固定了一些变量的函数的副本

下一篇: 函数是任意许多其他函数的总和