2
$\begingroup$

I am confused about the implementation of a global namespace in python . How are variable names mapped as keys to the objects they reference as values ,since namespace is implemented as a dictionary? If keys of a typical python dict are “objects” themselves, why are variables called keys if they are just references not the actual objects?

$\endgroup$
6
  • 2
    $\begingroup$ I don’t quite get what you are asking. Are you confused how variables (as source strings, runtime objects, …?) are treated as keys for the global dict? Are you confused how, generally, objects are treated as keys of dicts given reference semantics? Or something else entirely? Do you already understand how string objects are used as keys in dict objects? $\endgroup$ Commented Jul 7 at 7:03
  • $\begingroup$ Please correct me if I am wrong . I understand that variables are names that point to objects ( string, int, float…) but they are added to the global namespace which is under the hood implemented as a dictionary . Moreover ,what I know is that a typical python dictionary has (keys that can be any immutable and hashable object ) but the variables as names in the namespace are considered to be keys. What are they actually , are they just holding the address of object (values ). Please explain this Example: x=5 in terms of its implementation as in a namespace ( dictionary if it is the case) $\endgroup$
    – Silah
    Commented Jul 7 at 7:30
  • $\begingroup$ You can access the global dictionary itself with globals() to inspect it and see how it (apparently) behaves. I also don't understand what you're asking — the question seems to answer itself when it says that the variable names are mapped as keys to the objects they reference as values, but clearly that isn't what you want to know! You can edit your question. $\endgroup$
    – Michael Homer
    Commented Jul 7 at 7:56
  • $\begingroup$ Umm I am not being able to clearly ask . Let me put it in a better way . I am asking what is the difference between an internal implementation of a dictionary and a global namespace. Are the variable names treated as keys ? I ‘ll give an example: dic={“citrus “: “orange”} . citrus=“orange” . Now citrus here is a variable. How is the string “citrus” implementation in memory as a key different from variable citrus as a key in namespace? $\endgroup$
    – Silah
    Commented Jul 7 at 8:13
  • 1
    $\begingroup$ I'm guessing your confusion is actually with variables, not the use of globals and their keys. It seems like you are stuck on a sort of use-mention distinction between the variable as something used by Python and the variable as something represented by Python, with the challenge of separating the two without infinitely recursing between the concepts. Do you understand how locals work, i.e. how a local variable maps to locals or closures? $\endgroup$ Commented Jul 7 at 8:20

1 Answer 1

3
$\begingroup$

Python allows you to inspect the global scope with the globals() function. Let's try it out:

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <class '_frozen_importlib.BuiltinImporter'>,
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>}

We can create a new variable in scope:

x = 5

and then look at the globals dictionary again:

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None,
'__loader__': <class '_frozen_importlib.BuiltinImporter'>,
'__spec__': None, '__annotations__': {},
'__builtins__': <module 'builtins' (built-in)>, 'x': 5}

We can see that there is a new key, x, with the name of the variable we created and the value I assigned to it. It's the name of the variable, as a string, that is the key here.

We can use that string name as a key directly if we like:

>>> globals()["x"] = "hello"
>>> x
'hello'

You can see that the value of the x variable has changed when I updated the value in the globals() dictionary at the key "x". The language runtime understood to take that variable name and get it from the dictionary, and vice-versa. In this way, the global variables and the dictionary entries really are identified with one another.

This is a reasonable enough way of implementing variable scopes in a dynamically-typed language: you can use dictionary/map/table lookup semantics that you already have to drive your variables. JavaScript's global scopes work the same way, for example. The language, whichever one it is, just turns a read or write of a variable to an access to the scope dictionary at the key determined by the variable's name.

Python also exposes local variables the same way (using locals()), but JavaScript doesn't. You can imagine that the interpreter always holds on to two references to dictionaries, one for global variables and one for locals, and looks up any given variable in the corresponding dictionary. This is something that the language implementation knows to do — it's not happening "within" the user-level program, so you don't have to write globals["x"] = 5 every time you want to make an assignment, you just write the variable name and it does the rest internally.

Lots of small programming language implementations follow exactly this strategy for their variables: they give each scope a dictionary (map, table, hash, ...) for all the variables in it and turn every variable access into dictionary access, and that's it. This is convenient for implementation, because you can just make a data structure from the standard library and use it the way it's meant to be used, including for creating predefined scopes, printing it out for debugging, or lots of other common tasks.


There are a lot of fine implementation details behind the scenes here. A language doesn't need to use the same implementation strategy internally as it exposes to the user, as long as the observable behaviour is the same. High-performance JavaScript implementations generally try to optimise away these kinds of lookup, for example.

For the level of understanding you're looking for, we can treat any access to a variable as translating to a lookup in a specific dictionary using the variable's name, as a string, as the key. The implementation inherently knows where to find that dictionary for the current scope, and it knows it has to treat a variable that way when it sees one.

How string lookup inside a dictionary works is also an implementation detail. You could imagine that as a big list of pairs (key, value) and a for loop that does a linear search through the whole list to find a matching key and return the value that came with it. This has the right semantics, but it's slower than ideal, and real implementations will likely use a more efficient data structure and lookup algorithm. It doesn't matter whether the key came from a variable name, a string literal, or user input, the dictionary will work the same way regardless.

$\endgroup$
9
  • $\begingroup$ I want to thank you for such clear explanation. This helped me revisit my concept . I understood. Actually with so many resources all over the internet, plus considering one is a beginner, it is really hard to grasp the basics technically and then moving on to advanced topics $\endgroup$
    – Silah
    Commented Jul 7 at 9:06
  • $\begingroup$ Are there good resources online that can help me gain and strengthen my understanding about the topics relevant to how programming languages work internally ? Also , do I really need to know about this in depth to write efficient programs or does it just depend on whether I am opting to learn about the workings of interpreted languages’ implementation? $\endgroup$
    – Silah
    Commented Jul 7 at 9:12
  • 3
    $\begingroup$ I don't think you need to understand the internals of the implementations at this point. Those can get very complicated. For any real-world efficiency question, the contribution of the language is something you determine by profiling rather than inspection, and in most cases the program body will dominate anyway (and in any case, concerns about efficiency are probably premature optimisation right now). Most users of programming languages don't have in-depth knowledge of the implementation details of the language they are using. $\endgroup$
    – Michael Homer
    Commented Jul 7 at 9:28
  • $\begingroup$ Thanks once again! $\endgroup$
    – Silah
    Commented Jul 7 at 9:37
  • 3
    $\begingroup$ FWIW, in (common implementations of) Python locals are just represented as a dict of the user requests it, but not actually stored as such. In CPython, locals are an array of pointers, with variable names compiled to indices into that array. $\endgroup$ Commented Jul 7 at 11:51

Not the answer you're looking for? Browse other questions tagged .