[Python-ideas] For-loop variable scope: simultaneous possession and ingestion of cake

Arnaud Delobelle arnodel at googlemail.com
Wed Oct 15 10:46:28 CEST 2008

2008/10/14 Dillon Collins <dillonco at comcast.net>:
> On Tuesday 14 October 2008, Arnaud Delobelle wrote:
>> On 14 Oct 2008, at 05:03, Dillon Collins wrote:
>> > On Monday 13 October 2008, Arnaud Delobelle wrote:
>> >> It's inefficient because it works by deconstructing and
>> >> reconstructing
>> >> the function bytecode.
>> >
>> > That's not necessary.  Just make a new closure for it.  Here's some
>> > code (I
>> > was bored/curious).  The function reclose_kwds is provided for
>> > fun.   Enjoy:
>> But that doesn't work with global variables, does it?  Globals are the
>> reason why I had to scan the bytecode
> Nope.  However, I expect that globals would be even easier.  If you want to
> freeze all the variables, you can just replace func_globals with
> func_globals.copy().  Otherwise, you can replace it with some proxy object
> that would read from your dict and fall back to the real globals if
> necessary.  (Probably subclass dict with the __missing__ method.)

I guess you're right.  My version was just an adaptation of the 'bind'
decorator that I mentioned above, where only *some* non local
variables were 'frozen', so I had to change the bytecode for that.  I
tried just to adapt it but it was the wrong approach!
Anyway here is another version, without using bytecode introspection or ctypes:

def new_closure(vals):
    args = ','.join('x%i' % i for i in range(len(vals)))
    f = eval("lambda %s:lambda:(%s)" % (args, args))
    return f(*vals).func_closure

def localize(f):
    f_globals = dict((n, f.func_globals[n]) for n in f.func_code.co_names)
    f_closure = ( f.func_closure and
                  new_closure([c.cell_contents for c in f.func_closure]) )
    return type(f)(f.func_code, f_globals, f.func_name,
                   f.func_defaults, f_closure)


More information about the Python-ideas mailing list