lambda & scope

Alex Martelli aleaxit at yahoo.com
Tue Nov 7 09:41:12 EST 2000


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


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


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

A class whose instances are callable is really a simple way to
do generic 'hand-built closures'.  A lambda (with default
valued args for injection-into-scope) is simpler, though
a bit limited.  A local function (with default valued args)
may give more flexibility (and it's no worse than a lambda
in terms of 'complication', you just to have to invent a name):

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)

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"...!-)


Alex






More information about the Python-list mailing list