2 votes

Les compréhensions de listes Python3 ne fonctionnent pas comme prévu

Je suis en train de mettre en œuvre, en ce moment, la forme de Lagrange du polynôme d'interpolation en Python.

Il est composé de la somme des polynômes avec lesquels j'ai commencé. En donnant une liste de points (x, y) à ajuster, je calcule d'abord le polynôme de ces composantes en utilisant le code suivant :

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

def produit(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: produit([(x - xj)/(xs[0] - xj) for xj in xs if xs[0] != xj])

Jusqu'à présent, tout fonctionne comme il se doit, comme :

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

comme le dit la théorie. De manière naturelle, j'essaie de généraliser cela pour calculer chaque composant du polynôme dans une liste. Pour y parvenir, j'entoure l'expression lambda d'une autre compréhension de liste, remplaçant chaque occurrence d'accès indexé par xs par xi et itérant xi sur xs :

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

En voyant ce code, je serais d'accord avec beaucoup de confiance pour dire que le tout premier élément de cette liste est identique à p0. Cependant, il s'avère :

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

et il en va de même pour tous les éléments de p. Je dois donc manquer quelque chose soit dans les compréhensions de liste, soit dans les expressions lambda. Qu'est-ce que c'est? Merci d'avance pour votre aide.

1voto

Dani Mesejo Points 29634

Le problème que vous rencontrez est connu sous le nom de fermeture de liaison tardive, fondamentalement toutes les fonctions travaillent avec le dernier xi, une solution possible est d'utiliser des arguments par défaut :

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))

Résultat

1.0
0.0
0.0

En savoir plus

  1. Python lambda's binding to local values

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X