1

I want to build a container of Hermite polynomials (link to scipy's hermite doc) of different orders. From what the doc says, I expect scipy.special.hermite to accept the order n and return a function - an Hermite polynomial of order n.

This seems to work fine with single functions. But when I try to use a list of Hermitte polynomials by realising them as lambda functions, it seems they will all be reset to the last polynomial:

from scipy.special import hermite
base_funcs = [lambda x: hermite(i)(x) for i in range(5)]

[f(1) for f in base_funcs]
Out[40]: [-20.0, -20.0, -20.0, -20.0, -20.0]
hermite(0)(1)
Out[41]: 1.0
hermite(4)(1)
Out[42]: -20.0

Is there a way to initiate a container of different Hermite polynomials properly, without previous elements being overwritten by subsequent ones in the container apprehension statement? Thanks!

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Vim
  • 1,436
  • 2
  • 19
  • 32
  • 4
    That's the [late binding closure *gotcha*](https://docs.python-guide.org/writing/gotchas/#late-binding-closures). See the link for suggestions on how to fix it, or search for that term here on stackoverflow (e.g. https://stackoverflow.com/questions/37791680/scipy-optimize-minimize-slsqp-with-linear-constraints-fails/37792650#37792650). – Warren Weckesser Apr 29 '19 at 09:41
  • 1
    @WarrenWeckesser thanks the suggestions made in your answer work for me. – Vim Apr 29 '19 at 09:48

1 Answers1

0

As Warren's comment says, this is due to Python's late binding mechanism. To circumvent it, one solution is to include the loop variable as one of the function's default arguments. i.e.

[lambda x, i=i: hermite(i)(x) for i in range(5)]

Suggested reading: https://docs.python-guide.org/writing/gotchas/#late-binding-closures.

Vim
  • 1,436
  • 2
  • 19
  • 32