2

I am implementing at the moment Lagrange form of interpolating polynomial in Python.

It consists of sum of polynomials I started with. Given list of points (x, y) to be fitted, I calculate first of these components polynomial with following code:

def f(x):
  return x**2 - 1

def product(l):
  from functools import reduce
  return reduce(lambda x,y: x*y, l)

xs = [2,3,5]
ys = [f(x) for x in xs]

p0 = lambda x: product([(x - xj)/(xs[0] - xj) for xj in xs if xs[0] != xj])

So far, everything works as it should, as:

p0(2) = 1.0
p0(3) = 0.0
p0(5) = 0.0

as the theory says. In natural way, I am trying to generalize that to calculate every component polynomial into a list. In order to achieve this, I surround the lambda expression with another list comprehension, replacing every occurence of indexed access to xs with xi and iterating xi over xs:

p = [lambda x: product([(x - xj)/(xi - xj) for xj in xs if xi != xj]) for xi in xs]

Seeing this code, I would agree with much confidence that the very first element of this list is the same as p0. However, it turns out:

p[0](2) = 0.0
p[0](3) = 0.0
p[0](5) = 1.0

and the same holds for all elements of p. I must be missing something in either list comprehensions or lambda expressions. What is that? Thanks for help in advance.

1 Answers1

1

The problem you are facing is known as a late bind closure, basically all functions work with the last xi, a possible solution is to use default arguments:

def f(x):
    return x ** 2 - 1


def product(l):
    from functools import reduce
    return reduce(lambda x, y: x * y, l)


xs = [2, 3, 5]
ys = [f(x) for x in xs]

p0 = lambda x: product([(x - xj) / (xs[0] - xj) for xj in xs if xs[0] != xj])

p = [lambda x, xi=xi: product([(x - xj) / (xi - xj) for xj in xs if xi != xj]) for xi in xs]

print(p[0](2))
print(p[0](3))
print(p[0](5))

Output

1.0
0.0
0.0

Further

  1. Python lambda's binding to local values
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
  • I started to write my answer, but your is better, get a plus! – baldr Oct 25 '18 at 10:34
  • Now it is working correctly, thank you very much, but I am still wondering, even after reading articles provided, what is the point of such mechanism? When is it really useful? Could you explain/provide some example? – Michał Kaczanowicz Oct 25 '18 at 10:37