Re: updating locals() and globals() (WAS: How do I do this? (eval() on the left hand side))
On Wed, 8 Dec 2004 20:22:52 -0500, Terry Reedy [EMAIL PROTECTED] wrote: To respond to and summarize several posts in this discussion: Within a function, where the local namespace is distinct from the global (module) namespace, CPython usually implements the local namespace internally as a fixed-length array. When this is true, locals() is a *copy* of the local namespace and not the namespace itself. Once that dict is created, the history of how it was created is immediately forgotten, just as with any other ordinary Python dict. That dict can be bound to a name or other target and modified like any other dict, and there could be reasons to do so. However, modifying it has no more effect on the local namespace than modifying any other local dict. It doesn't appear to be _quite_ ordinary though (note that print d['x'] inside does print 3 the first time and 5 after the d['x']=5 assignment, but is not returned in d when d returns in the results): I think I'd rather locals() totally refuse updates than allow retrievable updates in a way that leaves me wondering what kind of object it is and what happens to it when it is exported from a function (some kind of closure stuff involved in converting a proxy to a dict? (will speculation)) ;-/ def f(): ... x = 3 ... d = locals() ... D = dict(locals()) ... print 'x', x ... print d['x'],d['x'] ... d['x'] = 5 ... print 'x', x ... print d['x'],d['x'] ... print D['x'], D['x'] ... D['x'] = 7 ... print d['x'],d['x'] ... print D['x'], D['x'] ... return d, D, locals() ... d,D,L = f() x 3 d['x'] 3 x 3 d['x'] 5 D['x'] 3 d['x'] 5 D['x'] 7 d {'x': 3, 'd': {...}, 'D': {'x': 7, 'd': {...}}} D {'x': 7, 'd': {'x': 3, 'd': {...}, 'D': {...}}} L {'x': 3, 'd': {...}, 'D': {'x': 7, 'd': {...}}} L['d']['x'] # not 5 3 L['D']['x'] # is 7 7 d['x'] 3 D['x'] 7 Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list
Re: updating locals() and globals() (WAS: How do I do this? (eval() on the left hand side))
Steve, I don't think I understand. Here is what I just tried: ' def f(): x = 3 d = locals() print x print d['x'] d['x'] = 5 print x ' f() 3 3 3 ' In your example, x had not yet been initialised, maybe. What I am seeing is that x does not seem to update when being assigned to - I guess this is what you are referring to by being unreliable. But unreliable sounds kinda vague and intermittent, and I assume that is not the case here - What is the Rule(tm)? Thanks Caleb On Wed, 08 Dec 2004 16:59:23 GMT, Steven Bethard [EMAIL PROTECTED] wrote: Peter Hansen wrote: Nick Coghlan wrote: Generally, altering the contents of the dicts returned by locals() and globals() is unreliable at best. Nick, could you please comment on why you say this about globals()? I've never heard of any possibility of unreliability in updating globals() and, as far as I know, a large body of code exists which does in fact rely on this -- much of mine included. ;-) Updating locals() is unreliable. Updating globals() is fine, AFAIK. http://docs.python.org/lib/built-in-funcs.html I believe that the only time that locals() is updatable is when locals() is globals(): locals() is globals() True x Traceback (most recent call last): File interactive input, line 1, in ? NameError: name 'x' is not defined locals()['x'] = 3 x 3 def f(): ... print locals() is globals() ... locals()['x'] = 3 ... print x ... f() False Traceback (most recent call last): File interactive input, line 1, in ? File interactive input, line 4, in f NameError: global name 'x' is not defined Steve -- http://mail.python.org/mailman/listinfo/python-list
Re: updating locals() and globals() (WAS: How do I do this? (eval() on the left hand side))
Caleb Hattingh wrote: Steve, I don't think I understand. Here is what I just tried: ' def f(): x = 3 d = locals() print x print d['x'] d['x'] = 5 print x ' f() 3 3 3 ' In your example, x had not yet been initialised, maybe. What I am seeing is that x does not seem to update when being assigned to - I guess this is what you are referring to by being unreliable. Yes, that was my intent. In the same way that my x was not initialized, your x is not updated. locals() is readable but not writable in any case where locals() is not globals(), I believe. But unreliable sounds kinda vague and intermittent, and I assume that is not the case here - What is the Rule(tm)? Unfortunately, I don't think there is a Rule(tm) because the behavior of locals() (and globals()?) are implementation details. I remember hearing an explanation of why locals() is not writable that had to do with something about efficiency and the call stack (or something like that)... Steve -- http://mail.python.org/mailman/listinfo/python-list
Re: updating locals() and globals() (WAS: How do I do this? (eval() on the left hand side))
Steven Bethard wrote: I remember hearing an explanation of why locals() is not writable that had to do with something about efficiency and the call stack (or something like that)... IIRC, the function local namespace (in CPython) is kept internally as a static array, rather than as a dictionary, which dramatically speeds (function-local) name lookups. However, this also means that all local names must be determinable at function-definition time. In contrast, the global namespace is a true Python dictionary. Where globals() returns a reference to that dictionary, locals() (when locals() is not globals()) constructs a separate dictionary from the static array containing the local namespace. In effect, globals() gives a reference while locals() gives a copy, with standard Python reference/copy semantics applying. (Note also that functions which use exec cannot use the static namespace optimization, and thus tend to be *much* slower than normal functions (in addition to being a huge security problem). I don't know, however, whether locals() can update the local namespace in such un-optimized functions. Whether it actually does so or not, relying on such special-case behavior would be extremely foolish to do...) Of course, I'm just going off of what I remember having been said elsewhere on c.l.p., and I wouldn't recommend anyone betting their life savings on the reliability of my memory... :) Jeff Shannon Technician/Programmer Credit International -- http://mail.python.org/mailman/listinfo/python-list
Re: updating locals() and globals() (WAS: How do I do this? (eval() on the left hand side))
To respond to and summarize several posts in this discussion: Within a function, where the local namespace is distinct from the global (module) namespace, CPython usually implements the local namespace internally as a fixed-length array. When this is true, locals() is a *copy* of the local namespace and not the namespace itself. Once that dict is created, the history of how it was created is immediately forgotten, just as with any other ordinary Python dict. That dict can be bound to a name or other target and modified like any other dict, and there could be reasons to do so. However, modifying it has no more effect on the local namespace than modifying any other local dict. Terry J. Reedy -- http://mail.python.org/mailman/listinfo/python-list