Early PEP draft (For Python 3000?)
I would like to re-suggest a suggestion I have made in the past, but with a mild difference, and a narrower scope. Name: Attribute access for all namespaces Rationale: globals() access is conceptually the same as setting the module's attributes but uses a different idiom (access of the dict directly). Also, locals() returns a dict, which implies it can affect the local scope, but quietly ignores changes. Using attribute access to access the local/global namespaces just as that is used in instance namespaces and other modules' namespaces, could reduce the mental footprint of Python. Method: All namespace accesses are attribute accesses, and not direct __dict__ accesses. Thus globals() is replaced by a "module" keyword (or "magic variable"?) that evaluates to the module object. Thus, reading/writing globals in module X, uses getattr/setattr on the module object, just like doing so in module Y would be. locals() would return be replaced by a function that returns the frame object (or a weaker equivalent of a frame object) of the currently running function. This object will represent the local namespace and will allow attribute getting/setting to read/write attributes. Or it can disallow attribute setting. Examples: global x ; x = 1 Replaced by: module.x = 1 or: globals()[x] = 1 Replaced by: setattr(module, x, 1) locals()['x'] = 1 # Quietly fails! Replaced by: frame.x = 1 # Raises error x = locals()[varname] Replaced by: x = getattr(frame, varname) Advantages: - Python becomes more consistent w.r.t namespacing and scopes. Disadvantages: - "module" is already possible by importing one's own module, but that is: * Confusing and unnecessarily requires naming one's self redundantly (Making renaming of the module a bit more difficult). * Not easily possible in a __main__/importable module. * No equivalent for locals() - Automatic script conversion may be difficult in some use cases of globals()/locals()
Eyal Lotem wrote:
locals()['x'] = 1 # Quietly fails! Replaced by: frame.x = 1 # Raises error
Or even better, replaced by frame.x = 1 # Does the right thing The frame object knows enough to be able to find the correct locals slot and update it, so there's no need for this to fail. -- Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg.ewing@canterbury.ac.nz +--------------------------------------+
On 10/11/05, Eyal Lotem <eyal.lotem@gmail.com> wrote:
locals()['x'] = 1 # Quietly fails! Replaced by: frame.x = 1 # Raises error
What about the possibility of making this hypothetic frame object an indexable, such that frame[0] is the current scope, frame[1] is the calling scope, etc.? On the same lines, what about closure[0] for the current frame, while closure[1] resolves to the closure the function was defined in? These would ensure that you could reliably access any namespace you would need, without nasty stack tricks and such, and would make working around some of the limitation of the closures, when you have such a need. One might even consider a __resolve__ to be defined in any namespace, allowing all the namespace resolution rules to be overridden by code at any level.
Calvin Spealman <ironfroggy@gmail.com> wrote:
On 10/11/05, Eyal Lotem <eyal.lotem@gmail.com> wrote:
locals()['x'] = 1 # Quietly fails! Replaced by: frame.x = 1 # Raises error
What about the possibility of making this hypothetic frame object an indexable, such that frame[0] is the current scope, frame[1] is the calling scope, etc.? On the same lines, what about closure[0] for the current frame, while closure[1] resolves to the closure the function was defined in? These would ensure that you could reliably access any namespace you would need, without nasty stack tricks and such, and would make working around some of the limitation of the closures, when you have such a need. One might even consider a __resolve__ to be defined in any namespace, allowing all the namespace resolution rules to be overridden by code at any level.
-1000 If you want a namespace, create one and pass it around. If the writer of a function or method wanted you monkeying around with a namespace, they would have given you one to work with. As for closure monkeywork, you've got to be kidding. Closures in Python are a clever and interesting way of keeping around certain things, but are actually unnecessary with the existance of class and instance namespaces. Every example of a closure can be re-done as a class/instance, and many end up looking better. - Josiah
On 10/14/05, Josiah Carlson <jcarlson@uci.edu> wrote:
Calvin Spealman <ironfroggy@gmail.com> wrote:
On 10/11/05, Eyal Lotem <eyal.lotem@gmail.com> wrote:
locals()['x'] = 1 # Quietly fails! Replaced by: frame.x = 1 # Raises error
What about the possibility of making this hypothetic frame object an indexable, such that frame[0] is the current scope, frame[1] is the calling scope, etc.? On the same lines, what about closure[0] for the current frame, while closure[1] resolves to the closure the function was defined in? These would ensure that you could reliably access any namespace you would need, without nasty stack tricks and such, and would make working around some of the limitation of the closures, when you have such a need. One might even consider a __resolve__ to be defined in any namespace, allowing all the namespace resolution rules to be overridden by code at any level.
-1000 If you want a namespace, create one and pass it around. If the writer of a function or method wanted you monkeying around with a namespace, they would have given you one to work with.
If they want you monkeying around with their namespace or not, you can do so with various tricks introspecting the frame stack and other internals. I was merely suggesting this as something more standardized, perhaps across the various Python implementations. It would also provide a single point of restriction when you want to disable such things.
As for closure monkeywork, you've got to be kidding. Closures in Python are a clever and interesting way of keeping around certain things, but are actually unnecessary with the existance of class and instance namespaces. Every example of a closure can be re-done as a class/instance, and many end up looking better.
i mostly put that in there for completeness.
Calvin Spealman <ironfroggy@gmail.com> wrote:
On 10/14/05, Josiah Carlson <jcarlson@uci.edu> wrote:
Calvin Spealman <ironfroggy@gmail.com> wrote:
On 10/11/05, Eyal Lotem <eyal.lotem@gmail.com> wrote:
locals()['x'] = 1 # Quietly fails! Replaced by: frame.x = 1 # Raises error
What about the possibility of making this hypothetic frame object an indexable, such that frame[0] is the current scope, frame[1] is the calling scope, etc.? On the same lines, what about closure[0] for the current frame, while closure[1] resolves to the closure the function was defined in? These would ensure that you could reliably access any namespace you would need, without nasty stack tricks and such, and would make working around some of the limitation of the closures, when you have such a need. One might even consider a __resolve__ to be defined in any namespace, allowing all the namespace resolution rules to be overridden by code at any level.
-1000 If you want a namespace, create one and pass it around. If the writer of a function or method wanted you monkeying around with a namespace, they would have given you one to work with.
If they want you monkeying around with their namespace or not, you can do so with various tricks introspecting the frame stack and other internals. I was merely suggesting this as something more standardized, perhaps across the various Python implementations. It would also provide a single point of restriction when you want to disable such things.
What I'm saying is that whether or not you can modify the contents of stack frames via tricks, you shouldn't. Why? Because as I said, if the writer wanted you to be hacking around with a namespace, they should have passed you a shared namespace. From what I understand, there are very few (good) reasons why a user should muck with stack frames, among them because it is quite convenient to write custom traceback printers (like web CGI, etc.), and if one is tricky, limit the callers of a function/method to those "allowable". There may be other good reasons, but until you offer a use-case that is compelling for reasons why it should be easier to access and/or modify the contents of stack frames, I'm going to remain at -1000. - Josiah
participants (4)
-
Calvin Spealman -
Eyal Lotem -
Greg Ewing -
Josiah Carlson