Accessing Function Variables from Sub-functions

Licheng Fang fanglicheng at gmail.com
Thu Oct 11 06:11:44 EDT 2007


On Apr 14 2003, 10:30 pm, Alex Martelli <al... at aleax.it> wrote:
> Sebastian Wilhelmi wrote:
> > Hi,
>
> > I would like to do the following:
>
> > -------8<-------8<-------8<-------8<-------
> > def test ():
> >     count = 0
> >     def inc_count ():
> >         count += 1
> >     inc_count ()
> >     inc_count ()
> >     print count
>
> > test ()
> > -------8<-------8<-------8<-------8<-------
>
> > This doesn't work (and I even understand, why ;-)
>
> Specifically: a nested function cannot *RE-BIND* a variable of
> an outer function.
>

Sorry to dig up this old thread, but I would like to know what's the
rationale is. Why can't a nested function rebind a variable of an
outer function?

>
>
> > One solution is the following, which I however do not see as very
> > clean or nice.
>
> > -------8<-------8<-------8<-------8<-------
> > def test ():
> >     count = [0]
> >     def inc_count ():
> >         count[0] += 1
> >     inc_count ()
> >     inc_count ()
> >     print count[0]
>
> > test ()
> > -------8<-------8<-------8<-------8<-------
>
> > Now my question: Is there some way to achieve this with a nicer
> > syntax?
>
> Depends on your tastes in syntax, e.g.:
>
> def test():
>     class Bunch: pass
>     loc = Bunch()
>     loc.count = 0
>     def inc_count():
>         loc.count += 1
>     inc_count()
>     inc_count()
>     print loc.count
>
> or:
>
> def test():
>     test.count = 0
>     def inc_count():
>         test.count += 1
>     inc_count()
>     inc_count()
>     print test.count
>
> and no doubt quite a few others.

I was trying to write a function that creates another function and
returns it when I came across this problem. These two solutions have a
difference:

def M():
    M.c = 0
    class Bunch:
        pass
    Bunch.c = 0
    def f():
        M.c += 1
        Bunch.c += 1
        print M.c, Bunch.c
    return f

>>>f = M()
>>>f2 = M()
>>> f()
1 1
>>> f()
2 2
>>> f()
3 3
>>> f2()
4 1
>>> f2()
5 2
>>> f2()
6 3

The created functions share their variables binded to the outer
function, but have their separate copies of variables bundled in a
class.

Is binding name to the function object a python way to use 'static'
variables? But how to initialize them?

>
> > Using 'global' would not count, as that would make a variable
> > unnecessarily known to the outside.
>
> The two solutions above outlined differ in this respect -- variable
> 'loc' in the former is local to function test, while function attribute
> test.count in the latter is "known to the outside" (it survives each
> execution of test and can be examined "from the outside").
>
> Class Bunch (or some highly refined version thereof) IS typically
> around whenever I program, see for example:
>
> http://mail.python.org/pipermail/python-list/2002-July/112007.html
>
> for a typical presentation.  Having available the MetaBunch there
> described, I'd start the function as follows:
>
> def test():
>     class Bunch(MetaBunch): count=0
>     loc = MetaBunch()
>     def inc_count():
>         loc.count += 1
>
> etc.  I do find such constructs often handy...
>
> Alex




More information about the Python-list mailing list