binding a reference to a variable

Bengt Richter bokr at oz.net
Thu Apr 11 17:33:58 EDT 2002


On Thu, 11 Apr 2002 08:56:32 -0700, Patrick Miller <patmiller at llnl.gov> wrote:

>Bengt writes>
>> >>> def set(name, val, ns=locals()):
>>  ...     ns[name]=val
>>  ...     return val
>
>Bengt noted that 'ns' is local to the declaration module of the
>'def set.'  
>
I also noted
"Of course, def set ... must be executed where it can capture ns=locals()
for use inside the function, where locals() is another space (and read-only)."
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

... i.e., that locals() inside a function is different and read-only,
which would predict the following.

>The workaround for that is
>
>def set(name,val):
>   import sys
>   ns = sys._getframe().f_back.f_locals # local dictionary of caller
>   ...
>
>BUT WARNING!!!!! There is a bigger problem --  Changes to the local
>dictionary are NOT reflected in the state of the execution.
>
unless locals() is globals() => 1
as is apparently normally the case at module scope, e.g.,

 +---< locagloba.py >-------------
 |print 'locagloba id(locals())=%s, id(globals())=%s' % (id(locals()), id(globals()))
 |def set(name, val, ns=locals()):
 |    ns[name]=val
 |    return val
 |set('z',456)
 |print z, locals()['z']
 +--------------------------------
 Python 2.2 (#28, Dec 21 2001, 12:21:22) [MSC 32 bit (Intel)] on win32
 Type "help", "copyright", "credits" or "license" for more information.
 >>> import locagloba
 locagloba id(locals())=8029232, id(globals())=8029232
 456 456
 >>> locagloba.z
 456

 >>> print 'interactive id(locals())=%s, id(globals())=%s' % (id(locals()), id(globals()))
 interactive id(locals())=7989472, id(globals())=7989472
 >>> locals() is globals()
 1
 >>> locagloba.z
 456

OTOH, might as well use globals() in the first place ;-)

>The following does not work as intended....
>
>def f():
>   a = 7
>   L = locals()
>   print L.keys() # Prints ['a','L'] or some such
>   L['a'] = 99  # Update the value in L
>   print a      # But wait!  This prints out '7'
>
>The issue is the implementation of the code object supporting f.
>The value of the locals dictionary is created on the fly by
>the call to locals().  The actual values of the local variables
>are on a tiny, predefined stack frame that is used by the bytecode
>interpreter wherein local variables are known only by an
>integer offset.
>
>Creating true "local" variables is astonishly tricky.
>
>You can actually figure out where names map into the frame instance
>(weave does (or will do) it), but it is messy and very implementation
>dependent.
>
But hiding that mess is the job of an implementation ;-)

>From what's been posted, ISTM that making locals() read/write
inside a function is feasible, with a performance hit. Probably
no one has wanted it badly enough to do it at all, never mind finding
a way to penalize only the locals()-modifying users.

Regards,
Bengt Richter



More information about the Python-list mailing list