# list of polynomial functions

Marc 'BlackJack' Rintsch bj_666 at gmx.net
Fri Jun 16 04:15:21 EDT 2006

```In <mailman.7114.1150412705.27775.python-list at python.org>, Tim Chase
wrote:

> My understanding is that the lambda-defined functions are not
> called until the actual application thereof, with the
>
> 	mypolys = make_polys(8)
> 	mypolys[5](2) #the lambda call happens here, no?

Yes, that's right.

> </F>'s original statement read like a koan...there was more in it
> than I was getting out of it.  There seem to be several concepts
> I've not yet wrapped my head around.  My understanding (likely
> wrong) was that "lambda" was sort of like defining a function
> inline, along the lines of
>
> 	def f(x):
> 		return x+5
>
> being somewhat equiv to
>
> 	k = lambda x: x+5
>
> you could then do
>
> 	>>> f(20)
> 	25
> 	>>> j = f
> 	>>> j(20)
> 	25
> 	>>> k(20)
> 	25
> 	>>> j = k
> 	>>> j(20)
> 	25
>
> There does seem to be some subtle difference, as
>
> 	>>> f
> 	<function f at 0xb7d87e9c>
> 	>>> k
> 	<function <lambda> at 0xb7d8c0d4>
>
> "k" clearly knows it's a <lambda> just as "f" knows its an "f"
> (whether asked for by the aliased name or not).

That understanding is mostly correct.  Just that there's no subtile
difference.  `k` doesn't know it's a lambda function, it's just an
ordinary function at this point which happens to have the name '<lambda>'.
That's somewhat unusual but it behaves like any ``def``-ed function.

> [lightbulb begins to go on...sorta]
>
> However, in the OP's example, slightly modified, it seems that
> polys, even when it doesn't exist in the calling scope, it
> doesn't matter.
>
>  >>> def mp(n):
> ...     p = lambda x: 1
> ...     polys = [p]
> ...     for i in range(n):
> ...             polys.append(lambda x: polys[i](x)*x)
> ...     return polys
> ...
>  >>> f = mp(5)
>  >>> polys
> Traceback (most recent call last):
>    File "<stdin>", line 1, in ?
> NameError: name 'polys' is not defined
>  >>> for p in f: print p(3)
> ...
> 1
> Traceback (most recent call last):
>    File "<stdin>", line 1, in ?
>    File "<stdin>", line 5, in <lambda>
> :
> :
> :
>
> I'm curious why the very first attempt to call p(3) doesn't bomb
> out with the NameError that "polys" wasn't defined before it even
> got to the point of attempting to call it.

Well, because `polys` does not exist in the module scope.  But it exists
in the local scope of the functions in `f`.

An example:

In [2]:def outer(a):
.2.:    b = 42
.2.:    def inner(c):
.2.:        print a, b, c
.2.:        print locals()
.2.:
.2.:    return inner
.2.:

In [3]:f = outer(1)

In [4]:f(2)
1 42 2
{'a': 1, 'c': 2, 'b': 42}

If `outer` returns `inner` the inner function still has a reference to the
locals of the enclosing function.  So they won't go away if the outer
function returns.  `a` and `b` are looked up when `f` is called.  That's a
problem if you create more than one function in `outer` and use a name
from outer's locals that changes:

In [7]:def pitfall():
.7.:    functions = list()
.7.:    for i in range(3):
.7.:        functions.append(lambda: i)
.7.:    print 'pitfall: i=%d' % i
.7.:    return functions
.7.:

In [8]:for function in pitfall():
.8.:    print function()
.8.:
pitfall: i=2
2
2
2

At the time the list with the functions is returned `i` is 2.  So if you
call any of the functions it looks up this `i`.

Ciao,
Marc 'BlackJack' Rintsch

```