free variables /cell objects question

gangesmaster tomerfiliba at gmail.com
Thu Jan 25 11:50:11 EST 2007


[Steven]
> My solution is, don't try to have one function do too much. Making a list
> of foos should be a separate operation from making a single foo:

that's exactly what my second example does (as well as my production
code)

[Paul]
> But it does work as expected, if your expectations are based on what
> closures actually do.

yet, i find what closures actually do, to be logically wrong.
moreover, it means the frame object must be kept alive for no reason...
or in my case, two frame objects per foo-function.

> The Python idiom is:
...
> def foo(n=n):

besides of being ugly, the def f(n=n) idiom is very bad,
programatically speaking. what if the user chooses to be a smartass
and call with n = 7? or what if the function's signature is
meaningful? (as it is in my case)

anyway, this talk is not going anywhere.
thanks for the info, and i'll see how i manage to optimize my code
from here.

-tomer

On Jan 25, 4:51 pm, Steven D'Aprano
<s... at REMOVE.THIS.cybersource.com.au> wrote:
> On Thu, 25 Jan 2007 04:29:35 -0800, Paul Rubin wrote:
> > "gangesmaster" <tomerfil... at gmail.com> writes:
> >> what i see as a bug is this code not working as expected:
>
> >> >>> def make_foos(names):
> >> ...     funcs = []
> >> ...     for n in names:
> >> ...             def foo():
> >> ...                     print "my name is", n
> >> ...             funcs.append(foo)
> >> ...     return funcs
>
> > But it does work as expected, if your expectations are based on what
> > closures actually do.
>
> >> i have to create yet another closure, make_foo, so that the name
> >> is correctly bound to the object, rather than the frame's slot:
>
> > The Python idiom is:
>
> >    def make_foos(names):
> >        funcs = []
> >        for n in names:
> >                def foo(n=n):
> >                        print "my name is", n
> >                funcs.append(foo)
> >        return funcs
>
> > The n=n in the "def foo" creates the internal binding that you need.Hmmm... I thought that the introduction of nested scopes removed the need
> for that idiom. Its an ugly idiom, the less I see it the happier I am.
>
> And I worry that it will bite you on the backside if your "n=n" is a
> mutable value.
>
> My solution is, don't try to have one function do too much. Making a list
> of foos should be a separate operation from making a single foo:
>
> >>> def makefoo(name):...     def foo():
> ...             return "my name is " + name
> ...     return foo
> ...>>> makefoo("fred")()
> 'my name is fred'
> >>> def makefoos(names):...     foos = []
> ...     for name in names:
> ...             foos.append(makefoo(name))
> ...     return foos
> ...>>> L = makefoos(["fred", "wilma"])
> >>> L[0]()
> 'my name is fred'
> >>> L[1]()'my name is wilma'
>
> That makes it easier to do unit testing too: you can test your makefoo
> function independently of your makefoos function, if that's important.
>
> If you absolutely have to have everything in one function:
>
> >>> def makefoos(names):...     def makefoo(name):
> ...             def foo():
> ...                     return "my name is " + name
> ...             return foo
> ...     L = []
> ...     for name in names:
> ...             L.append(makefoo(name))
> ...     return L
> ...>>> L = makefoos(["betty", "barney"])
> >>> L[0]()
> 'my name is betty'
> >>> L[1]()'my name is barney'
>
> Best of all, now I don't have to argue as to which binding behaviour is
> more correct for closures!!! *wink*
> 
> --
> Steven.




More information about the Python-list mailing list