Statement local namespaces summary (was Re: python3: 'where' keyword)
Nick Coghlan
ncoghlan at iinet.net.au
Fri Jan 14 07:05:08 EST 2005
Nick Coghlan wrote:
> as equivalent to:
>
> def __use_stmt():
> <use-suite>
> def _in_clause():
> <in-suite>
> return <names>
> return _in_clause()
> __use_stmt_args = {}
> <names> = __use_stmt()
> del __use_stmt
>
The more I think about this return-based approach, the less I like it. It could
probably be made to work, but it just feels like a kludge to work around the
fact that the only mechanisms available for altering the bindings of local names
are assignment and definition statements.
For class namespaces, getattr(), setattr() and delattr() work a treat, and
globals() works fine for module level name binding.
locals() is an unfortunate second class citizen, since it writes to it aren't
propagated back to the executing frame. Programmatic interrogation of locals is
fine, but update is impossible.
What would be interesting is if locals() returned a dictionary whose __setitem__
method invoked PyFrame_LocalsToFast on the relevant frame, instead of a vanilla
dictionary as it does now.
Then locals()["x"] = foo would actually work properly.
Notice that you can get this effect today, by using exec to force invocation of
PyFrame_LocalsToFast:
Py> def f():
... n = 1
... def g(outer=locals()):
... outer["n"] += 1
... g() # Does not affect n
... print n
... exec "g()" # DOES affect n
... print n
...
Py> f()
1
2
(The call to g() has to be inside the exec statement, since the exec statement
evaluation starts with a call to PyFrame_FastToLocals).
Assuming a writeable locals(), the semantics for the normal case are given by:
============
def __use_stmt(__outer):
<use-suite>
<in-suite>
__inner = locals()
for name in <names>:
__outer[name] = __inner[name]
__use_stmt(locals())
del __use_stmt
============
And for the 'delayed execution' case:
============
def __named_use_stmt(__outer):
<use-suite>
def __delayed_block():
<in-suite>
__inner = locals()
for name in <names>:
__outer[name] = __inner[name]
return __delayed_block
<in-name> = __named_use_stmt(locals())
del __named_use_stmt
============
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
More information about the Python-list
mailing list