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
More information about the Python-list
mailing list