[Python-ideas] Tweaking closures and lexical scoping to include the function being defined

Ron Adam ron3200 at gmail.com
Fri Sep 30 07:25:04 CEST 2011

On Thu, 2011-09-29 at 17:45 -1000, Carl Matthew Johnson wrote:
> On Sep 29, 2011, at 5:35 PM, Ron Adam wrote:
> >   @set_closure(x=0)
> >   def adder(y):
> >       nonlocal x
> >       x += y
> >       return x
> Won't work as written because the nonlocal will cause an error before the decorator is applied.

You are right!  I didn't see that.

But, first lets understand what nonlocal actually does.  Doing a lot of
comparisons, it tells the compiler to generate STORE_DEREF byte codes
instead of STORE_FAST byte codes.

In otherwords the nonlocal feature can be moved into the Function class
constructor.  It doesn't need to actually be in the function it self.

So the Function class could take a list of "nonlocal" names, along with
the a dict of closure names and values.  Then, the function the
decorator is on, will work as if it had nonlocal statement in it on
those names.

   def set_closure(**kwds):   
       def wrapper(f):
           f = type(f)(f, closure=kwds, nonlocals=kwds.keys())
           return f
       return wrapper

   def adder(y):
       x += y
       return x

That would get around the nonlocal error.

> The other day, I suggested we add the ability for decorators to have a __prepare__ method
> that creates the namespace the function being created will use,
> but it was shot down as impractical. It would however do what you want to do here.

I think it would have the same problems, because the namespace isn't
associated to the function at the time it's created.

If the above is out, then were back to syntax. 

How about anonymous wrappers?

  def adder(y):
      nonlocal x
      x += y
      return x

which would be the same as...

  def _(x=0):
      def adder(y):
          nonlocal x
          x += y
          return x
      return adder
  adder = _()

And of course decorators could be stacked above that.



More information about the Python-ideas mailing list