This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: weird behavior when assigning locals() to a variable
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: nnorwitz, sambayer
Priority: normal Keywords:

Created on 2005-12-22 00:04 by sambayer, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (4)
msg27123 - (view) Author: Samuel Bayer (sambayer) Date: 2005-12-22 00:04
Tried this on Python 2.3.3, under Redhat Linux
Enterprise 3, and on Python 2.3.5, under MacOS X
10.4.3. Don't have access to 2.4 anywhere, so I can't
test it, but I took a look at the bug queue and can't
find any reference to this problem.

The following function yields a KeyError when run:

def foo():
    b = locals()
    c = 5
    print b["c"]

The following function does not:

def foo():
    b = locals()
    c = 5
    locals()
    print b["c"]

There's no typo there. After referencing locals()
again, without updating the value of b, the printout works.

Note that b and locals(), as I believe is intended, are
identical:

def foo():
    b = locals()
    c = 5
    print id(b)
    print b.has_key()
    print id(locals())
    print b.has_key()

yields, when run:

>>> foo()
285984
False
285984
True

This has GOT to be a bug. 
msg27124 - (view) Author: Samuel Bayer (sambayer) Date: 2005-12-22 00:25
Logged In: YES 
user_id=40146

OK, it doesn't got to be a bug. After staring at the
documentation for locals(), I realize that locals() is only
updated when it's called again. 

So it's not a bug, but it is a little odd. It's the only
namespace-like object you can't reliably use as a format
string argument. Consider the following:

>>> b = globals()
>>> c = 5
>>> print "%(c)d" % b

This prints the expected value. Ditto this:

>>> Class Foo: pass
>>> a = Foo(); b = a.__dict__
>>> a.c = 5
>>> print "%(c)d" % b

Only with locals(), inside a function, does this pattern
fail. I imagine it would be expensive to make work, though.

Never mind...
msg27125 - (view) Author: Neal Norwitz (nnorwitz) * (Python committer) Date: 2005-12-22 05:48
Logged In: YES 
user_id=33168

If you have suggestions for how we can improve the doc, let
us know.  I'll close this bug report since you seem to agree
it's not a bug.
msg27126 - (view) Author: Samuel Bayer (sambayer) Date: 2005-12-22 13:24
Logged In: YES 
user_id=40146

This morning, as I thought about it some more, I had some vain hope that the 
__getitem__ method of that particular dictionary could be updated to refresh 
the dictionary, but after trolling through the source a little, I see that it's 
really just a regular dictionary, and it doesn't know anything about where it 
came from. Would it be dangerous to add the current stack frame to the 
locals() dictionary as a value like __frame___? Perhaps that would screw up the 
garbage collection by adding a circular reference.

In any case, the current documentation for locals() reads:

"Update and return a dictionary representing the current local symbol table. 
Warning: The contents of this dictionary should not be modified; changes 
may not affect the values of local variables used by the interpreter."

I'd say something like

"Update and return a dictionary representing the current local symbol table. 
Warnings: The contents of this dictionary should not be modified; changes 
may not affect the values of local variables used by the interpreter. Also, this 
dictionary is not guaranteed to be synchronized with the actual local 
environment; if the local symbol table changes between the time you retrieve 
the value of locals() and the time you use it, you won't see the changes."
History
Date User Action Args
2022-04-11 14:56:14adminsetgithub: 42714
2005-12-22 00:04:14sambayercreate