[Tutor] Global namespace/dictionary
Steven D'Aprano
steve at pearwood.info
Sun Dec 22 11:58:33 CET 2013
On Sat, Dec 21, 2013 at 02:22:32PM -0500, Keith Winston wrote:
> On Sat, Dec 21, 2013 at 12:56 PM, <tutor-request at python.org> wrote:
>
> > py> x = 23
> > py> d = globals()
> > py> d['x']
> > 23
> > py> d['x'] = 42
> > py> x
> > 42
> >
>
>
> Well this is sort of fascinating, but a bit confusing: I was playing with
> this, and it seems like the global dictionary includes not just the name
> but the entire contents of every dictionary within it...
Not just every dictionary, but every string, every list, every object in
the global scope. That's the whole point of a namespace -- it is the
"thing" which holds variable names and values.
So if you have a variable "x" set to the dict {1: "one"} and a variable
"y" set to the list [1, 2, 4, 8], then your global namespace will be:
globals()
=> {"y": [1, 2, 4, 8], "x": {1: "one"}, ...}
(plus other stuff I'm not showing). Now don't worry about that being
wasteful of memory. The objects (the dict, the list, etc.) have to be
*somewhere* in memory, and that place happens to be the global
namespace. Python is very efficient here, and doesn't duplicate values:
the dictionary returned by globals() is NOT a copy of the variables, it
actually is the very same dictionary that Python uses. So although it is
quite large to print, there is nothing redundant about it.
> that seems
> implausibly redundant, so maybe that's just something about how exploring a
> dictionary functions recursively, or something? Maybe it's correct to say
> that any dictionaries within a namespace are stored in that namespace,
> though that doesn't really sound right.
No, that's exactly right. And the same applies for lists, strings, ints,
floats and any other object. They have to live somewhere.
> >>> d = globals()
> >>> fubar = {1: 'spam', 'eggs': 2}
> >>> d
> {'__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>,
> '__doc__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>,
> 'fubar': {1: 'spam', 'eggs': 2}, 'd': {...}, '__package__': None}
Now this is a really good example of Python at work. You have a global
variable d which is bound to the global namespace dict. That's the same
dictionary which Python uses for global variables. But d is itself a
global dictionary! Which means that the global namespace dict, which we
call "d", has to include a reference back to itself.
Sure enough, if you print d, it shows d as a key. What does the value
for d show? Well, it obviously cannot show the entire globals, since
that would recurse infinitely:
print(d)
=> {'__name__': '__main__', '__doc__': None,
'd': {'__name__': '__main__', '__doc__': None,
'd': {'__name__': '__main__', '__doc__': None,
'd': {'__name__': '__main__', '__doc__': None,
'd': ... # and so on, forever
Instead, Python recognises the recursion, and short-cuts the process by
only displaying "..." inside the dict:
print(d)
=> {'__name__': '__main__', '__doc__': None,
'd': {...} }
(Obviously I've simplified the contents a bit, for brevity.)
You can experiment with such recursive structures in Python very easily.
Here's a simple example:
L = [] # Empty list.
L.append(L)
print(L)
L.append(42)
print(L[0] == L)
--
Steven
More information about the Tutor
mailing list