On 03/05/13 11:29, Nick Coghlan wrote:
An exchange in one of the enum threads prompted me to write down
something I've occasionally thought about regarding locals(): it is
currently severely underspecified, and I'd like to make the current
CPython behaviour part of the language/library specification. (We
recently found a bug in the interaction between the __prepare__ method
and lexical closures that was indirectly related to this
underspecification)

Fixing the underspecification is good. Enshrining a limitation as the
one correct way, not so good.


* at function scope, locals() must return a *snapshot* of the current
locals and free variables. Subsequent execution must not change the
contents of the returned mapping and changes to the returned mapping
must not change the execution environment.

If we were designing the language from scratch, with no concern for
optimizing function execution, would we want this as a language feature?
I don't believe that there is anyone who would say:

"I really want locals() to behave differently inside functions from how
it behaves inside classes and the global scope, as a feature in and of
itself."

Obviously CPython introduces that limitation for good reason, and I don't
wish to suggest that this is the wrong thing to do, but it is a trade-off,
and some implementations may wish to make other trade-offs, or even find
a way to avoid it altogether.

E.g. IronPython and Jython both allow this:


def func():
...     x = 1; del x
...     locals()['x'] = 2
...     print x
...
func()
2

And why not? In and of itself, writing to locals() inside a function is
no worse a thing to do than writing to locals() inside a class or global
scope. It's not something actively harmful that must be prohibited, so why
prohibit it?

I think that conforming Python implementations should be allowed a choice
between two fully-specified behaviours, the choice between them being a
"quality of implementation" issue:


- locals() may return a read-only or frozen mapping containing a snapshot
  of the current locals and free variable, in which case subsequent
  execution must not change the contents of the returned mapping, and
  changing the returned mapping is not possible;

- locals() may return an ordinary dict, in which case it must be the
  actual execution namespace, or a proxy to it. Subsequent execution
  will change the contents of the returned mapping, and changes to the
  mapping must change the execution environment.


Code can determine at runtime which capability is provided by inspecting
the type of the returned mapping: if isinstance(locals(), dict) then you
have support for modifying the executable environment, if not, you don't.

Obviously if you wish to write platform-agnostic code, you have to target
the least behaviour, which would be read-only locals. But there's lots of
code that runs only under Jython or IronPython, and if somebody really
needs to write to locals(), they can target an implementation that
provides that feature.



--
Steven
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to