lambda & scope

John J. Lee phrxy at csv.warwick.ac.uk
Wed Nov 8 12:11:28 EST 2000


> "Alex Martelli" <aleaxit at yahoo.com> wrote:
>
> "John J. Lee" <phrxy at csv.warwick.ac.uk> wrote in message
> news:Pine.SOL.4.30.0011062003110.29419-100000 at mimosa.csv.warwick.ac.uk...
>     [snip]
> > say you have:
> >
> > def fred(variable, parameter):
> >     return parameter*variable**2
>
> OK so far.
>
>
> > and you want to do something in the spirit of:
> >
> > def wilma():
> >     (...)
> >     parameter = 3.4
> >     call_fred(lambda x: wilma(x, parameter), args, args, args)
>
> The spirit is willing, but the flesh is weak.  The recursive
> call to wilma is a bother.  I'll guess you mean something like:
>
> def call_fred(funz, *args):
>     for arg in args:
>         something_wonderful(funz(arg))
>
> and:
>
> def wilma(parameter):
>     call_fred(lambda x: fred(x, parameter), 1.2, 3.4, 5.6, 7.8)

Yes, fred(x, parameter) is of course what I meant - sorry.

>
> > Because you know that call_fred wants as its first argument a function
> > that only takes one argument (above doesn't work due to Python's
> > three-level scope).
>
> ...and can be made to work easily and classically with "hand-built
> closure":
>
> def wilma(parameter):
>     call_fred(lambda x, parm=parameter: fred(x, parm), 1.2, 3.4, 5.6,
7.8)
>
> the 'default-valued argument' parm injects its default-value in
> the lambda's scope, with its name.

But then you end up with another function with two variables, don't you?
You could always just change the function (fred()) that you want to call,
but it's annoying that while you can get a one-argument function from an
n-argument function when you're in the global scope, you can't do the same
when you're inside a function (apparently).

> > Probably 'don't do that' is a good answer, but I wondered if there was
> > another one?  Actually I think there is a way that would work in Mark
> > Lutz's book, using a class, but is there a simpler way?
[...]
> def wilma(parameter):
>     def localfun(x, parm=parameter):
>         # you can insert statements here...
>         return fred(x, parm)
>     call_fred(localfun, 1.2, 3.4, 5.6, 7.8)

But that's a function of two variables still.  I can't remember the exact
circumstances now (I rewrote it a better way), but roughly the reason I
wanted to do this was because I have a function that expects a function as
a argument, and that (latter) function is expected by the (former)
function to take only one argument.  Er, hope that's clear...

In the local function you have above, python would complain, when it got
around to calling localfun from within call_fred, that localfun has two
formal parameters whereas it was only given one argument in the function
call.

I realised quickly that for my purpose (using the leastsq function in the
Multipack library for NumPy) there was no need to do this, but I was
wondering how you could do it anyway.

> Other ways tend to be more _complicated_, or at least _complex_
> (and refined).  For example, using the built-in 'new' module to
> build a function-object on the fly from a code-object with a
> chance to specify default-values...
>
> import new
>
> def wilma3(parameter):
>     afunc = new.function(fred.func_code,globals(),'fred',(parameter,))
>     call_fred(afunc, 1.2, 3.4, 5.6, 7.8)
>
> ...but I wouldn't exactly call this "simpler"...!-)

Aha, I think (haven't read the documentation for 'new' yet) that's what I
was looking for - thanks.


John




More information about the Python-list mailing list