[Tutor] learning nested functions

eryksun eryksun at gmail.com
Wed Jul 10 22:54:53 CEST 2013


On Mon, Jul 8, 2013 at 2:26 AM, Tim Hanson <tjhanson at yahoo.com> wrote:
>
> No problem so far.  I made a change and ran it again:
>
>>>> def f1():
>         x=88
>         def f2():
>                 print(x)
>                 x=99
>                 print(x)
>         f2()

You need to use a "nonlocal" declaration (3.x only). Using nonlocal
explicitly creates a closure. In your first example this was done
implicitly. But since you're assigning to x, the compiler assumes you
want a local unless you tell it otherwise.

    def f1():
        x = 88
        def f2():
            nonlocal x
            print(x)
            x = 99
            print(x)
        return f2

    >>> f2 = f1()
    >>> f2()
    88
    99

To pull this off Python creates a cell object that's shared by both
frames. The cell lives as long as it's referenced:

   >>> f2.__closure__[0].cell_contents
   99
   >>> sys.getrefcount(f2.__closure__[0]) - 1
   1

I subtracted 1 for the getrefcount call. The reference is only 1
because the frame for f1 is already garbage collected. If you call f1
again, it creates a new cell for 'x' and a new f2. As you can imagine
the bytecode for working with cells is different, and this affects f1
and f2 equally. Instead of LOAD_FAST and STORE_FAST, they use
LOAD_DEREF and STORE_DEREF.


More information about the Tutor mailing list