Re: updating locals() and globals() (WAS: How do I do this? (eval() on the left hand side))

2004-12-09 Thread Bengt Richter
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))

2004-12-08 Thread Caleb Hattingh
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))

2004-12-08 Thread Steven Bethard
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))

2004-12-08 Thread Jeff Shannon
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))

2004-12-08 Thread Terry Reedy
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