[Python-Dev] Tightening up the specification for locals() (original) (raw)
Steven D'Aprano steve at pearwood.info
Fri May 3 04:43:41 CEST 2013
- Previous message: [Python-Dev] Tightening up the specification for locals()
- Next message: [Python-Dev] Tightening up the specification for locals()
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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
- Previous message: [Python-Dev] Tightening up the specification for locals()
- Next message: [Python-Dev] Tightening up the specification for locals()
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]